view SpriteObject.cpp @ 1005:8073f9a70e8b

CastSpellInfo::_427E01_cast_spell() more clean
author zipi
date Sat, 18 May 2013 18:36:08 +0100
parents d061180f2b42
children c45d51b3f4f4
line wrap: on
line source

#include <assert.h>

#include "SpriteObject.h"
#include "Party.h"
#include "TurnEngine.h"
#include "MapInfo.h"
#include "Math.h"
#include "ObjectList.h"
#include "Indoor.h"
#include "Outdoor.h"
#include "ParticleEngine.h"
#include "Time.h"
#include "Game.h"
#include "LOD.h"
#include "Actor.h"
#include "Events.h"

#include "mm7_data.h"
#include "MM7.h"








size_t uNumSpriteObjects;
SpriteObject pSpriteObjects[MAX_SPRITE_OBJECTS];

//----- (00404828) --------------------------------------------------------
SpriteObject::SpriteObject()
{
  field_22_glow_radius_multiplier = 1;
  uSoundID = 0;
  uFacing = 0;
  vVelocity.z = 0;
  vVelocity.y = 0;
  vVelocity.x = 0;
  uType = 0;
  uObjectDescID = 0;
  field_61 = 0;
  field_60_distance_related_prolly_lod = 0;
  field_20 = 0;
  uSpriteFrameID = 0;
  spell_skill = 0;
  spell_level = 0;
  spell_id = 0;
  field_54 = 0;
}

//----- (0042F5ED) --------------------------------------------------------
int SpriteObject::Create(int yaw, int pitch, int a4, int a5)
{
  //SpriteObject *v5; // eax@1
  signed int v6; // ebx@2
  //char *v7; // ecx@2
  //signed int result; // eax@6
  SpriteObject *v9; // ebx@7
  int v10; // edx@11
  int v11; // edi@18
  __int16 v12; // ax@18
  int v13; // ST2C_4@20
  int v14; // eax@20
  int v15; // [sp-28h] [bp-38h]@14
  int v16; // [sp-24h] [bp-34h]@11
  Vec3_int_ v17; // [sp-20h] [bp-30h]@11
  int *v18; // [sp-14h] [bp-24h]@11
  int *v19; // [sp-10h] [bp-20h]@11
  int *v20; // [sp-Ch] [bp-1Ch]@11
  //signed int v21; // [sp+8h] [bp-8h]@2
  int angle; // [sp+Ch] [bp-4h]@1
  int a4a; // [sp+1Ch] [bp+Ch]@20
  int a4b; // [sp+1Ch] [bp+Ch]@20
  int a5a; // [sp+20h] [bp+10h]@20

  //auto a1 = this;
  angle = yaw;
  //v5 = a1;
  if (!uObjectDescID)
    return -1;

  v6 = 1000;
  //v7 = (char *)&pSpriteObjects[0].uObjectDescID;
  /*v21 = 0;
  do
  {
    if ( !*(short *)v7 )
      break;
    v7 += 112;
    ++v6;
    v21 = v6;
  }
  while ( (signed int)v7 < (signed int)((char *)&pObjectList->uNumObjects + 2) );*/
  for (uint i = 0; i < MAX_SPRITE_OBJECTS; ++i)
    if (!pSpriteObjects[i].uObjectDescID)
    {
      v6 = i;
      break;
    }

  if ( v6 >= 1000 )
    return -1;
  field_64.x = vPosition.x;
  field_64.y = vPosition.y;
  v9 = &pSpriteObjects[v6];
  field_64.z = vPosition.z;

  assert(sizeof(SpriteObject) == 0x70);
  memcpy(v9, this, sizeof(*this));
  if ( a5 == 1 )
  {
    v20 = &v9->vPosition.z;
    v19 = &v9->vPosition.y;
    v18 = (int *)&v9->vPosition;
    v17.x = vPosition.x;
    v17.y = vPosition.y;
    v17.z = vPosition.z;
    v16 = 0;
    v10 = stru_5C6E00->uIntegerHalfPi + v9->uFacing;
    goto LABEL_16;
  }
  if ( a5 == 2 )
  {
    v20 = &v9->vPosition.z;
    v19 = &v9->vPosition.y;
    v18 = (int *)&v9->vPosition;
    v17.x = vPosition.x;
    v17.y = vPosition.y;
    v17.z = vPosition.z;
    v16 = 0;
    v10 = stru_5C6E00->uIntegerHalfPi + v9->uFacing;
    goto LABEL_14;
  }
  if ( a5 == 3 )
  {
    v20 = &v9->vPosition.z;
    v19 = &v9->vPosition.y;
    v18 = (int *)&v9->vPosition;
    v17.x = vPosition.x;
    v17.y = vPosition.y;
    v17.z = vPosition.z;
    v16 = 0;
    v10 = v9->uFacing - stru_5C6E00->uIntegerHalfPi;
LABEL_14:
    v15 = 8;
LABEL_17:
    Vec3_int_::Rotate(v15, v10, v16, v17, v18, v19, v20);
    goto LABEL_18;
  }
  if ( a5 == 4 )
  {
    v20 = &v9->vPosition.z;
    v19 = &v9->vPosition.y;
    v18 = (int *)&v9->vPosition;
    v17.x = vPosition.x;
    v17.y = vPosition.y;
    v17.z = vPosition.z;
    v16 = 0;
    v10 = v9->uFacing - stru_5C6E00->uIntegerHalfPi;
LABEL_16:
    v15 = 24;
    goto LABEL_17;
  }
LABEL_18:
  v11 = a4;
  v12 = 0;
  if ( a4 )
  {
    a4a = stru_5C6E00->Cos(angle);
    v13 = (unsigned __int64)(a4a * (signed __int64)stru_5C6E00->Cos(pitch)) >> 16;
    a4b = stru_5C6E00->Sin(angle);
    a5a = (unsigned __int64)(a4b * (signed __int64)stru_5C6E00->Cos(pitch)) >> 16;
    v14 = stru_5C6E00->Sin(pitch);
    v9->vVelocity.x = (unsigned int)(v13 * v11) >> 16;
    v9->vVelocity.y = (unsigned int)(a5a * v11) >> 16;
    v12 = (unsigned int)(v14 * v11) >> 16;
  }
  else
  {
    v9->vVelocity.y = 0;
    v9->vVelocity.x = 0;
  }
  v9->vVelocity.z = v12;

  if ( v6 >= (signed int)uNumSpriteObjects )
    uNumSpriteObjects = v6 + 1;
  return v6;
}

//----- (00471C03) --------------------------------------------------------
void SpriteObject::UpdateObject_fn0_ODM(unsigned int uLayingItemID)
{
  SpriteObject *v1; // esi@1
  ObjectDesc *v2; // ebx@1
  signed int v3; // edx@1
  int v4; // ecx@1
  int v5; // ST04_4@1
  int v6; // eax@1
  int v7; // ecx@1
  int v8; // edi@1
  int v9; // eax@4
  __int16 v10; // ax@7
  int v11; // edx@11
  int v12; // ecx@11
  signed int v13; // edx@14
  signed int v14; // edx@16
  int v15; // eax@24
  int v16; // eax@25
  int v17; // ST10_4@25
  signed int v18; // eax@25
  signed int v19; // eax@28
  Actor *v20; // edi@31
  int v21; // eax@41
  int v22; // ecx@43
  __int16 v23; // bx@45
  char v24; // al@46
  signed int i; // edi@50
  int v26; // edi@52
  int v27; // eax@52
  __int16 v28; // cx@55
  int v29; // eax@55
  signed int v30; // edi@59
  BSPModel *v31; // ecx@61
  ODMFace *v32; // edi@61
  int v33; // eax@62
  int v34; // ecx@62
  int v35; // eax@63
  Actor *v36; // ecx@67
  __int16 v37; // ax@67
  int v38; // eax@72
  int v39; // eax@72
  unsigned __int64 v40; // qax@72
  int v41; // eax@72
  unsigned __int8 v42; // sf@74
  unsigned __int8 v43; // of@74
  int v44; // eax@77
  __int16 v45; // bx@81
  int v46; // eax@85
  const char *v47; // [sp-8h] [bp-B0h]@83
  enum TEXTURE_TYPE v48; // [sp-4h] [bp-ACh]@46
  int v49; // [sp+Ch] [bp-9Ch]@52
  int v50; // [sp+10h] [bp-98h]@52
  Vec3_int_ v51; // [sp+14h] [bp-94h]@11
  Particle_sw Dst; // [sp+20h] [bp-88h]@45
  unsigned int uLayingItemID_; // [sp+88h] [bp-20h]@1
  int v54; // [sp+8Ch] [bp-1Ch]@1
  int v55; // [sp+90h] [bp-18h]@1
  int v56; // [sp+94h] [bp-14h]@11
  int v57; // [sp+98h] [bp-10h]@1
  int v58; // [sp+9Ch] [bp-Ch]@1
  int v59; // [sp+A0h] [bp-8h]@1
  Actor *v60; // [sp+A4h] [bp-4h]@11

  uLayingItemID_ = uLayingItemID;
  v1 = &pSpriteObjects[uLayingItemID];
  v58 = 0;
  v2 = &pObjectList->pObjects[v1->uObjectDescID];
  v57 = IsTerrainSlopeTooHigh(v1->vPosition.x, v1->vPosition.y);
  v3 = v1->vPosition.y;
  v4 = v1->vPosition.x;
  v5 = v2->uHeight;
  v55 = 0;
  v6 = ODM_GetFloorLevel(v4, v3, v1->vPosition.z, v5, &v59, &v55, 0);
  v7 = v6;
  v54 = v6;
  v8 = v6 + 1;
  if ( v1->vPosition.z <= v6 + 1 )
  {
    if ( v59 )
    {
      v9 = v6 + 60;
      if ( v55 )
        v9 = v7 + 30;
      sub_42F960_create_object(v1->vPosition.x, v1->vPosition.y, v9);
      SpriteObject::OnInteraction(uLayingItemID_);
      v7 = v54;
    }
  }
  else
  {
    v58 = 1;
  }
  v10 = v2->uFlags;
  if ( !(v10 & 0x20) )
  {
    if ( v58 )
    {
      v1->vVelocity.z -= LOWORD(pEventTimer->uTimeElapsed) * GetGravityStrength();
      goto LABEL_13;
    }
    if ( v57 )
    {
      v11 = v1->vPosition.y;
      v12 = v1->vPosition.x;
      v1->vPosition.z = v8;
      ODM_GetTerrainNormalAt(v12, v11, &v51);
      v1->vVelocity.z -= LOWORD(pEventTimer->uTimeElapsed) * GetGravityStrength();
      v56 = abs(v51.y * v1->vVelocity.y + v51.z * v1->vVelocity.z + v51.x * v1->vVelocity.x) >> 16;
      v60 = (Actor *)((unsigned __int64)(v56 * (signed __int64)v51.x) >> 16);
      v1->vVelocity.x += (unsigned int)(v56 * v51.x) >> 16;
      v60 = (Actor *)((unsigned __int64)(v56 * (signed __int64)v51.y) >> 16);
      v1->vVelocity.y += (unsigned int)(v56 * v51.y) >> 16;
      v60 = (Actor *)((unsigned __int64)(v56 * (signed __int64)v51.z) >> 16);
      v1->vVelocity.z += (unsigned int)(v56 * v51.z) >> 16;
LABEL_12:
      v7 = v54;
      goto LABEL_13;
    }
    if ( v10 & 0x40 )
    {
      if ( v1->vPosition.z < v7 )
        v1->vPosition.z = v8;
      if ( !_46BFFA_check_object_intercept(uLayingItemID_, 0) )
        return;
    }
    v1->vPosition.z = v8;
    if ( !(v2->uFlags & 0x80) || (v21 = -v1->vVelocity.z >> 1, v1->vVelocity.z = v21, (signed __int16)v21 < 10) )
      v1->vVelocity.z = 0;
    v60 = (Actor *)v1->vVelocity.x;
    v55 = 58500;
    v60 = (Actor *)((unsigned __int64)(58500i64 * (signed int)v60) >> 16);
    v1->vVelocity.x = (signed __int16)v60;
    v60 = (Actor *)v1->vVelocity.y;
    v60 = (Actor *)((unsigned __int64)(v55 * (signed __int64)(signed int)v60) >> 16);
    v55 = 58500;
    v1->vVelocity.y = (signed __int16)v60;
    v60 = (Actor *)v1->vVelocity.z;
    v60 = (Actor *)((unsigned __int64)(v55 * (signed __int64)(signed int)v60) >> 16);
    v22 = v1->vVelocity.x;
    v1->vVelocity.z = (signed __int16)v60;
    if ( v1->vVelocity.y * v1->vVelocity.y + v22 * v22 >= 400 )
      goto LABEL_12;
    v1->vVelocity.y = 0;
    v1->vVelocity.x = 0;
    if ( !(HIBYTE(v2->uFlags) & 1) )
      return;
    memset(&Dst, 0, 0x68u);
    v23 = v2->uFlags;
    Dst.x = (double)v1->vPosition.x;
    Dst.y = (double)v1->vPosition.y;
    Dst.z = (double)v1->vPosition.z;
    Dst.flt_10 = 0.0;
    Dst.flt_14 = 0.0;
    Dst.flt_18 = 0.0;
    if ( HIBYTE(v23) & 2 )
    {
      Dst.type = ParticleType_Bitmap | ParticleType_Rotating | ParticleType_8;
      Dst.uDiffuse = 0xFF3C1E;
      v24 = rand();
      v48 = (TEXTURE_TYPE)0;
LABEL_83:
      v47 = "effpar01";
    }
    else
    {
      if ( HIBYTE(v23) & 4 )
      {
        Dst.type = ParticleType_Line;
        Dst.uDiffuse = rand();
        Dst.timeToLive = 64;
        Dst.uTextureID = 0;
LABEL_89:
        Dst.flt_28 = 1.0;
        pGame->pParticleEngine->AddParticle(&Dst);
        return;
      }
      Dst.type = ParticleType_Bitmap | ParticleType_8;
      Dst.uDiffuse = rand();
      v24 = rand();
      v48 = (TEXTURE_TYPE)0;
LABEL_87:
      v47 = "effpar03";
    }
    Dst.timeToLive = (unsigned __int8)(v24 & 0x80) + 128;
    Dst.uTextureID = pBitmaps_LOD->LoadTexture(v47, v48);
    goto LABEL_89;
  }
LABEL_13:
  if ( v1->vPosition.z > v7
    && (v13 = v1->vPosition.x, v13 >= -32768)
    && v13 <= 32768
    && (v14 = v1->vPosition.y, v14 >= -32768)
    && v14 <= 32768
    && v1->vPosition.z <= 13000
    || !(v2->uFlags & 0x40) )
    goto LABEL_92;
  if ( v1->vPosition.z < v7 )
    v1->vPosition.z = v8;
  if ( _46BFFA_check_object_intercept(uLayingItemID_, 0) )
  {
LABEL_92:
    stru_721530.field_0 = 0;
    v55 = 0;
    stru_721530.prolly_normal_d = v2->uRadius;
    stru_721530.field_C = v2->uHeight;
    stru_721530.field_8 = 0;
    stru_721530.field_70 = 0;
    while ( 1 )
    {
      stru_721530.field_34.x = v1->vPosition.x;
      stru_721530.normal.x = stru_721530.field_34.x;
      v15 = v1->vPosition.y;
      stru_721530.uSectorID = 0;
      stru_721530.field_34.y = v15;
      stru_721530.normal.y = v15;
      stru_721530.field_34.z = v1->vPosition.z + stru_721530.prolly_normal_d + 1;
      stru_721530.normal.z = stru_721530.field_34.z;
      stru_721530.field_1C = v1->vVelocity.x;
      stru_721530.field_20 = v1->vVelocity.y;
      stru_721530.field_24 = v1->vVelocity.z;
      if ( stru_721530._47050A(0) )
        return;
      _46E889_collide_against_bmodels(0);
      v16 = WorldPosToGridCellZ(v1->vPosition.y);
      v17 = v1->vPosition.x;
      v58 = v16;
      v18 = WorldPosToGridCellX(v17);
      _46E26D_collide_against_sprites(v18, v58);
      if (PID_TYPE(v1->spell_caster_pid) != OBJECT_Player)
        _46EF01_collision_chech_player(0);
      if (PID_TYPE(v1->spell_caster_pid) == OBJECT_Actor)
      {
        v19 = PID_ID(v1->spell_caster_pid);
        if ( v19 >= 0 )
        {
          if ( v19 < (signed int)(uNumActors - 1) )
          {
            v56 = 0;
            if ( (signed int)uNumActors > 0 )
            {
              v60 = pActors;
              v20 = &pActors[v19];
              do
              {
                if ( v20->GetActorsRelation(v60) )
                  _46DF1A_collide_against_actor(v56, 0);
                ++v56;
                ++v60;
              }
              while ( v56 < (signed int)uNumActors );
            }
          }
        }
      }
      else
      {
        for ( i = 0; i < (signed int)uNumActors; ++i )
          _46DF1A_collide_against_actor(i, 0);
      }
      v26 = stru_721530.normal2.z - stru_721530.prolly_normal_d - 1;
      v27 = ODM_GetFloorLevel(
              stru_721530.normal2.x,
              stru_721530.normal2.y,
              stru_721530.normal2.z - stru_721530.prolly_normal_d - 1,
              v2->uHeight,
              &v49,
              &v50,
              0);
      if ( v59 && v26 < v27 + 60 )
      {
        if ( v50 )
          v44 = v27 + 30;
        else
          v44 = v54 + 60;
        sub_42F960_create_object(v1->vPosition.x, v1->vPosition.y, v44);
        SpriteObject::OnInteraction(uLayingItemID_);
        return;
      }
      if ( stru_721530.field_7C >= stru_721530.field_6C )
      {
        v1->vPosition.x = stru_721530.normal2.x;
        v1->vPosition.y = stru_721530.normal2.y;
        v1->vPosition.z = stru_721530.normal2.z - stru_721530.prolly_normal_d - 1;
        v1->uSectorID = LOWORD(stru_721530.uSectorID);
        if ( !(HIBYTE(v2->uFlags) & 1) )
          return;
        memset(&Dst, 0, 0x68u);
        v45 = v2->uFlags;
        Dst.x = (double)v1->vPosition.x;
        Dst.y = (double)v1->vPosition.y;
        Dst.z = (double)v1->vPosition.z;
        Dst.flt_10 = 0.0;
        Dst.flt_14 = 0.0;
        Dst.flt_18 = 0.0;
        if ( HIBYTE(v45) & 2 )
        {
          Dst.type = ParticleType_Bitmap | ParticleType_Rotating | ParticleType_8;
          Dst.uDiffuse = 0xFF3C1E;
          v24 = rand();
          v48 = (TEXTURE_TYPE)0;
          goto LABEL_83;
        }
        if ( HIBYTE(v45) & 4 )
        {
          Dst.type = ParticleType_Line;
          v46 = rand();
          Dst.uTextureID = 0;
          Dst.uDiffuse = v46;
          Dst.timeToLive = 64;
          goto LABEL_89;
        }
        Dst.type = ParticleType_Bitmap | ParticleType_8;
        Dst.uDiffuse = rand();
        v24 = rand();
        v48 = (TEXTURE_TYPE)0;
        goto LABEL_87;
      }
      v60 = (Actor *)((unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.x) >> 16);
      v1->vPosition.x += (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.x) >> 16;
      v60 = (Actor *)((unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.y) >> 16);
      v1->vPosition.y += (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.y) >> 16;
      v60 = (Actor *)((unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.z) >> 16);
      v28 = LOWORD(stru_721530.uSectorID);
      v1->vPosition.z += (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.z) >> 16;
      v29 = v1->vPosition.z;
      v1->uSectorID = v28;
      stru_721530.field_70 += stru_721530.field_7C;
      if ( v2->uFlags & 0x40 )
      {
        if ( v29 < v54 )
          v1->vPosition.z = v54 + 1;
        if ( !_46BFFA_check_object_intercept(uLayingItemID_, stru_721530.uFaceID) )
          return;
      }
      v30 = (signed int)PID_ID(stru_721530.uFaceID);
      if (PID_TYPE(stru_721530.uFaceID) == OBJECT_Decoration)
        break;
      if (PID_TYPE(stru_721530.uFaceID) == OBJECT_BModel)
      {
        v31 = &pOutdoor->pBModels[(signed int)stru_721530.uFaceID >> 9];
        v32 = &v31->pFaces[v30 & 0x3F];
        if ( v32->uPolygonType != 3 )
        {
          v56 = abs(v32->pFacePlane.vNormal.z * v1->vVelocity.z + v32->pFacePlane.vNormal.y * v1->vVelocity.y
                                                                + v32->pFacePlane.vNormal.x * v1->vVelocity.x) >> 16;
          if ( stru_721530.field_64 >> 3 > v56 )
            v56 = stru_721530.field_64 >> 3;
          v57 = v32->pFacePlane.vNormal.x;
          v57 = (unsigned __int64)(v56 * (signed __int64)v57) >> 16;
          v58 = v32->pFacePlane.vNormal.y;
          v58 = (unsigned __int64)(v56 * (signed __int64)v58) >> 16;
          v60 = (Actor *)v32->pFacePlane.vNormal.z;
          v60 = (Actor *)((unsigned __int64)(v56 * (signed __int64)(signed int)v60) >> 16);
          v1->vVelocity.x += 2 * v57;
          v1->vVelocity.y += 2 * v58;
          if ( v32->pFacePlane.vNormal.z <= 32000 )
          {
            v37 = 2 * (short)v60;
          }
          else
          {
            v36 = v60;
            v57 = 32000;
            v1->vVelocity.z += (signed __int16)v60;
            v58 = (unsigned __int64)(v57 * (signed __int64)(signed int)v36) >> 16;
            v37 = (unsigned int)(v57 * (int)v36) >> 16;
          }
          v1->vVelocity.z += v37;
LABEL_70:
          if ( BYTE3(v32->uAttributes) & 0x10 )
            EventProcessor(v32->sCogTriggeredID, 0, 1);
          goto LABEL_74;
        }
        v33 = v31->pVertices.pVertices[v32->pVertexIDs[0]].z;
        v34 = v1->vVelocity.x;
        v1->vPosition.z = v33 + 1;
        if ( v1->vVelocity.y * v1->vVelocity.y + v34 * v34 >= 400 )
          goto LABEL_70;
        LOWORD(v35) = 0;
        v1->vVelocity.z = 0;
        v1->vVelocity.x = 0;
        goto LABEL_73;
      }
LABEL_74:
      v58 = v1->vVelocity.x;
      v57 = 58500;
      v58 = (unsigned __int64)(58500i64 * v58) >> 16;
      v1->vVelocity.x = v58;
      v58 = v1->vVelocity.y;
      v58 = (unsigned __int64)(v57 * (signed __int64)v58) >> 16;
      v57 = 58500;
      v1->vVelocity.y = v58;
      v58 = v1->vVelocity.z;
      v58 = (unsigned __int64)(v57 * (signed __int64)v58) >> 16;
      ++v55;
      v43 = __OFSUB__(v55, 100);
      v42 = v55 - 100 < 0;
      v1->vVelocity.z = v58;
      if ( !(v42 ^ v43) )
        return;
    }
    v57 = integer_sqrt(v1->vVelocity.y * v1->vVelocity.y + v1->vVelocity.x * v1->vVelocity.x);
    v38 = stru_5C6E00->Atan2(
            v1->vPosition.x - pLevelDecorations[v30].vPosition.x,
            v1->vPosition.y - pLevelDecorations[v30].vPosition.y);
    v56 = v38;
    v39 = stru_5C6E00->Cos(v38);
    v60 = (Actor *)v39;
    v40 = v39 * (signed __int64)v57;
    v58 = v40 >> 16;
    v1->vVelocity.x = WORD1(v40);
    v41 = stru_5C6E00->Sin(v56 - stru_5C6E00->uIntegerHalfPi);
    v60 = (Actor *)v41;
    v35 = (unsigned __int64)(v41 * (signed __int64)v57) >> 16;
    v58 = v35;
LABEL_73:
    v1->vVelocity.y = v35;
    goto LABEL_74;
  }
}

//----- (0047136C) --------------------------------------------------------
void SpriteObject::UpdateObject_fn0_BLV(unsigned int uLayingItemID)
{
  SpriteObject *pSpriteObject; // esi@1
  ObjectDesc *pObject; // edi@1
  //int v3; // ST08_4@1
  //__int16 v4; // ax@5
  __int16 v5; // ax@7
  BLVFace *v6; // ecx@11
  BLVFace *v7; // eax@11
  signed int v8; // ebx@12
  int v9; // ecx@16
  __int16 v10; // di@18
  char v11; // al@19
  int v12; // eax@25
  int v13; // eax@31
  int v14; // ebx@34
  signed int v15; // ebx@46
  BLVFace *v16; // edi@48
  int v17; // eax@50
  int v18; // eax@52
  int v19; // ecx@52
  Vec3_short_ *v20; // ecx@53
  int v21; // ecx@57
  __int16 v22; // ax@57
  int v23; // edi@62
  int v24; // edi@62
  int v25; // eax@62
  unsigned __int64 v26; // qax@62
  unsigned __int8 v27; // sf@64
  unsigned __int8 v28; // of@64
  __int16 v29; // di@67
  char v30; // al@68
  const char *v31; // [sp-8h] [bp-98h]@19
  const char *v32; // [sp-8h] [bp-98h]@68
  enum TEXTURE_TYPE v33; // [sp-4h] [bp-94h]@19
  enum TEXTURE_TYPE v34; // [sp-4h] [bp-94h]@68
  Particle_sw Dst; // [sp+Ch] [bp-84h]@18
  //unsigned int uLayingItemID_; // [sp+74h] [bp-1Ch]@1
  //ObjectDesc *v37; // [sp+78h] [bp-18h]@1
  unsigned int uFaceID; // [sp+7Ch] [bp-14h]@4
  int v39; // [sp+80h] [bp-10h]@33
  Actor *v39b;
  int v40; // [sp+84h] [bp-Ch]@28
  int v41; // [sp+88h] [bp-8h]@34
  int v42; // [sp+8Ch] [bp-4h]@4

  //uLayingItemID_ = uLayingItemID;
  pSpriteObject = &pSpriteObjects[uLayingItemID];
  pObject = &pObjectList->pObjects[pSpriteObject->uObjectDescID];
  //v3 = pSpriteObject->vPosition.x;
  //v37 = &pObjectList->pObjects[pSpriteObject->uObjectDescID];
  pSpriteObject->uSectorID = pIndoor->GetSector(pSpriteObject->vPosition.x, pSpriteObject->vPosition.y, pSpriteObject->vPosition.z);
  v42 = BLV_GetFloorLevel(pSpriteObject->vPosition.x, pSpriteObject->vPosition.y, pSpriteObject->vPosition.z, pSpriteObject->uSectorID, &uFaceID);
  if ( abs(pSpriteObject->vPosition.x) > 32767
    || abs(pSpriteObject->vPosition.y) > 32767
    || abs(pSpriteObject->vPosition.z) > 20000
    || v42 <= -30000
    && (pSpriteObject->uSectorID == 0))
//     || (v42 = _46CEC3_get_floor_level(pSpriteObject->vPosition.x, pSpriteObject->vPosition.y, pSpriteObject->vPosition.z, v4, &uFaceID), v42 == -30000)) )
  {
    SpriteObject::OnInteraction(uLayingItemID);
    return;
  }
  v5 = pObject->uFlags;
  if ( v5 & 0x20 )
  {
LABEL_24:
    v8 = 0;
LABEL_25:
    stru_721530.field_0 = v8;
    uFaceID = v8;
    stru_721530.prolly_normal_d = pObject->uRadius;
    v12 = pObject->uHeight;
    stru_721530.field_84 = -1;
    stru_721530.field_C = v12;
    stru_721530.field_8 = v8;
    stru_721530.field_70 = v8;
    while ( 1 )
    {
      stru_721530.field_34.x = pSpriteObject->vPosition.x;
      stru_721530.normal.x = stru_721530.field_34.x;
      stru_721530.field_34.y = pSpriteObject->vPosition.y;
      stru_721530.normal.y = stru_721530.field_34.y;
      stru_721530.field_34.z = stru_721530.prolly_normal_d + pSpriteObject->vPosition.z + 1;
      stru_721530.normal.z = stru_721530.field_34.z;
      stru_721530.field_1C = pSpriteObject->vVelocity.x;
      stru_721530.field_20 = pSpriteObject->vVelocity.y;
      stru_721530.field_24 = pSpriteObject->vVelocity.z;
      stru_721530.uSectorID = pSpriteObject->uSectorID;
      if ( stru_721530._47050A(v8) )
        return;
      v40 = v8;
      do
      {
        _46E44E_collide_against_faces_and_portals(0);
        _46E0B2_collide_against_decorations();
        if (PID_TYPE(pSpriteObject->spell_caster_pid) != OBJECT_Player)
          _46EF01_collision_chech_player(1);
        v13 = pSpriteObject->spell_caster_pid;
        v42 = v8;
        if (PID_TYPE(v13) == OBJECT_Actor)
        {
          if ( (signed int)uNumActors > v8 )
          {
            v39b = pActors;//[0].word_000086_some_monster_id;
            do
            {
              //v41 = pActors[v1->field_58 >> 3].pMonsterInfo.uID - 1;
              //v14 = (signed __int64)((double)v41 * 0.3333333333333333);
              //v41 = *(short *)(v39 - 38) - 1;
              //if ( v14 != (unsigned int)(signed __int64)((double)v41 * 0.3333333333333333) )
				if( pActors[pSpriteObject->spell_caster_pid >> 3].pMonsterInfo.uID != v39b->pMonsterInfo.uID )
					//not sure: pMonsterList->pMonsters[v39b->word_000086_some_monster_id-1].uToHitRadius
					_46DF1A_collide_against_actor(v42, *((short *)&pMonsterList->pMonsters[v39b->word_000086_some_monster_id] - 73));
              ++v42;
              ++v39b;// += 836;
            }
            while ( v42 < (signed int)uNumActors );
            v8 = 0;
          }
        }
        else
        {
          if ( (signed int)uNumActors > v8 )
          {
            v39b = pActors;//[0].word_000086_some_monster_id;
            do
            {
              _46DF1A_collide_against_actor(v42++, *((short *)&pMonsterList->pMonsters[*(short *)v39b] - 73));
              ++v39b;
            }
            while ( v42 < (signed int)uNumActors );
          }
        }
        if ( _46F04E_collide_against_portals() )
          break;
        ++v40;
      }
      while ( v40 < 100 );
      if ( stru_721530.field_7C >= stru_721530.field_6C )
      {
        pSpriteObject->vPosition.x = stru_721530.normal2.x;
        pSpriteObject->vPosition.y = stru_721530.normal2.y;
        pSpriteObject->vPosition.z = stru_721530.normal2.z - stru_721530.prolly_normal_d - 1;
        pSpriteObject->uSectorID = LOWORD(stru_721530.uSectorID);
        if ( !(HIBYTE(pObject->uFlags) & 1) )
          return;
        memset(&Dst, v8, 0x68u);
        v29 = pObject->uFlags;
        Dst.x = (double)pSpriteObject->vPosition.x;
        Dst.y = (double)pSpriteObject->vPosition.y;
        Dst.z = (double)pSpriteObject->vPosition.z;
        Dst.flt_10 = 0.0;
        Dst.flt_14 = 0.0;
        Dst.flt_18 = 0.0;
        if ( v29 & 0x200 )
        {
          Dst.type = ParticleType_Bitmap | ParticleType_Rotating | ParticleType_8;
          Dst.uDiffuse = 0xFF3C1E;
          v30 = rand();
          v34 = (TEXTURE_TYPE)v8;
          v32 = "effpar01";
        }
        else
        {
          if ( v29 & 0x400 )
          {
            Dst.type = ParticleType_Line;
            Dst.uDiffuse = rand();
            Dst.timeToLive = 64;
            Dst.uTextureID = v8;
            Dst.flt_28 = 1.0;
            pGame->pParticleEngine->AddParticle(&Dst);
            return;
          }
          Dst.type = ParticleType_Bitmap | ParticleType_8;
          Dst.uDiffuse = rand();
          v30 = rand();
          v34 = (TEXTURE_TYPE)v8;
          v32 = "effpar03";
        }
        Dst.timeToLive = (unsigned __int8)(v30 & 0x80) + 128;
        Dst.uTextureID = pBitmaps_LOD->LoadTexture(v32, v34);
        Dst.flt_28 = 1.0;
        pGame->pParticleEngine->AddParticle(&Dst);
        return;
      }
      v40 = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.x) >> 16;
      pSpriteObject->vPosition.x += (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.x) >> 16;
      v40 = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.y) >> 16;
      pSpriteObject->vPosition.y += (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.y) >> 16;
      v40 = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.z) >> 16;
      pSpriteObject->vPosition.z += (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.z) >> 16;
      pSpriteObject->uSectorID = LOWORD(stru_721530.uSectorID);
      stru_721530.field_70 += stru_721530.field_7C;
      if ( pObject->uFlags & 0x40 && !_46BFFA_check_object_intercept(uLayingItemID, stru_721530.uFaceID) )
        return;
      v15 = (signed int)stru_721530.uFaceID >> 3;
      if (PID_TYPE(stru_721530.uFaceID) == OBJECT_Decoration)
      {
        v40 = integer_sqrt(pSpriteObject->vVelocity.x * pSpriteObject->vVelocity.x + pSpriteObject->vVelocity.y * pSpriteObject->vVelocity.y);
        v23 = stru_5C6E00->Atan2(pSpriteObject->vPosition.x - pLevelDecorations[v15].vPosition.x,
                pSpriteObject->vPosition.y - pLevelDecorations[v15].vPosition.y);
        v42 = stru_5C6E00->Cos(v23);
        v41 = (unsigned __int64)(v42 * (signed __int64)v40) >> 16;
        v24 = v23;
        pSpriteObject->vVelocity.x = (unsigned int)(v42 * v40) >> 16;
        v25 = stru_5C6E00->Sin(v23);
        v42 = v25;
        v26 = v25 * (signed __int64)v40;
        v41 = v26 >> 16;
        pSpriteObject->vVelocity.y = WORD1(v26);
      }
      else
      {
        if (PID_TYPE(stru_721530.uFaceID) != OBJECT_BModel)
          goto LABEL_64;
        stru_721530.field_84 = (signed int)PID_ID(stru_721530.uFaceID);
        v16 = &pIndoor->pFaces[v15];
        if ( v16->uPolygonType != 3 )
        {
          v42 = abs(v16->pFacePlane_old.vNormal.x * pSpriteObject->vVelocity.x + v16->pFacePlane_old.vNormal.z * pSpriteObject->vVelocity.z
                                                                    + v16->pFacePlane_old.vNormal.y * pSpriteObject->vVelocity.y) >> 16;
          if ( stru_721530.field_64 >> 3 > v42 )
            v42 = stru_721530.field_64 >> 3;
          v40 = v16->pFacePlane_old.vNormal.x;
          v40 = (unsigned __int64)(v42 * (signed __int64)v40) >> 16;
          v41 = v16->pFacePlane_old.vNormal.y;
          v41 = (unsigned __int64)(v42 * (signed __int64)v41) >> 16;
          v39 = v16->pFacePlane_old.vNormal.z;
          v39 = (unsigned __int64)(v42 * (signed __int64)v39) >> 16;
          pSpriteObject->vVelocity.x += 2 * v40;
          pSpriteObject->vVelocity.y += 2 * v41;
          if ( v16->pFacePlane_old.vNormal.z <= 32000 )
          {
            v22 = 2 * v39;
          }
          else
          {
            v21 = v39;
            v40 = 32000;
            pSpriteObject->vVelocity.z += v39;
            v41 = (unsigned __int64)(v40 * (signed __int64)v21) >> 16;
            v22 = (unsigned int)(v40 * v21) >> 16;
          }
          pSpriteObject->vVelocity.z += v22;
          if ( BYTE3(v16->uAttributes) & 0x10 )
            EventProcessor(pIndoor->pFaceExtras[v16->uFaceExtraID].uEventID, 0, 1);
          goto LABEL_63;
        }
        if ( pObject->uFlags & 0x80 )
        {
          v17 = -pSpriteObject->vVelocity.z >> 1;
          pSpriteObject->vVelocity.z = v17;
          if ( (signed __int16)v17 < 10 )
            pSpriteObject->vVelocity.z = 0;
          if ( BYTE3(v16->uAttributes) & 0x10 )
            EventProcessor(pIndoor->pFaceExtras[v16->uFaceExtraID].uEventID, 0, 1);
          goto LABEL_63;
        }
        v18 = pSpriteObject->vVelocity.y;
        v19 = pSpriteObject->vVelocity.x;
        pSpriteObject->vVelocity.z = 0;
        if ( v19 * v19 + v18 * v18 >= 400 )
        {
          if ( BYTE3(v16->uAttributes) & 0x10 )
            EventProcessor(pIndoor->pFaceExtras[v16->uFaceExtraID].uEventID, 0, 1);
          goto LABEL_63;
        }
        v20 = pIndoor->pVertices;
        pSpriteObject->vVelocity.z = 0;
        pSpriteObject->vVelocity.y = 0;
        pSpriteObject->vVelocity.x = 0;
        pSpriteObject->vPosition.z = v20[*v16->pVertexIDs].z + 1;
      }
LABEL_63:
      //v2 = v37;
LABEL_64:
      v41 = pSpriteObject->vVelocity.x;
      v40 = 58500;
      v41 = (unsigned __int64)(58500i64 * v41) >> 16;
      pSpriteObject->vVelocity.x = v41;
      v41 = pSpriteObject->vVelocity.y;
      v41 = (unsigned __int64)(v40 * (signed __int64)v41) >> 16;
      v40 = 58500;
      pSpriteObject->vVelocity.y = v41;
      v41 = pSpriteObject->vVelocity.z;
      v41 = (unsigned __int64)(v40 * (signed __int64)v41) >> 16;
      ++uFaceID;
      v28 = __OFSUB__(uFaceID, 100);
      v27 = uFaceID - 100 < 0;
      pSpriteObject->vVelocity.z = v41;
      if ( !(v27 ^ v28) )
        return;
      v8 = 0;
    }
  }
  if ( v42 <= pSpriteObject->vPosition.z - 3 )
  {
    pSpriteObject->vVelocity.z -= LOWORD(pEventTimer->uTimeElapsed) * GetGravityStrength();
    goto LABEL_24;
  }
  if ( !(v5 & 0x40) || _46BFFA_check_object_intercept(uLayingItemID, 0) )
  {
    v6 = pIndoor->pFaces;
    pSpriteObject->vPosition.z = v42 + 1;
    v7 = &v6[uFaceID];
    if ( v7->uPolygonType == 3 )
    {
      v8 = 0;
      pSpriteObject->vVelocity.z = 0;
    }
    else
    {
      if ( v7->pFacePlane_old.vNormal.z < 45000 )
        pSpriteObject->vVelocity.z -= LOWORD(pEventTimer->uTimeElapsed) * GetGravityStrength();
      v8 = 0;
    }
    v42 = pSpriteObject->vVelocity.x;
    uFaceID = 58500;
    v42 = (unsigned __int64)(58500i64 * v42) >> 16;
    pSpriteObject->vVelocity.x = v42;
    v42 = pSpriteObject->vVelocity.y;
    v42 = (unsigned __int64)(uFaceID * (signed __int64)v42) >> 16;
    uFaceID = 58500;
    pSpriteObject->vVelocity.y = v42;
    v42 = pSpriteObject->vVelocity.z;
    v42 = (unsigned __int64)(uFaceID * (signed __int64)v42) >> 16;
    v9 = pSpriteObject->vVelocity.x;
    pSpriteObject->vVelocity.z = v42;
    if ( v9 * v9 + pSpriteObject->vVelocity.y * pSpriteObject->vVelocity.y < 400 )
    {
      pSpriteObject->vVelocity.z = v8;
      pSpriteObject->vVelocity.y = v8;
      pSpriteObject->vVelocity.x = v8;
      if ( !(pObject->uFlags & 1) )
        return;
      memset(&Dst, v8, 0x68u);
      v10 = pObject->uFlags;
      Dst.x = (double)pSpriteObject->vPosition.x;
      Dst.y = (double)pSpriteObject->vPosition.y;
      Dst.z = (double)pSpriteObject->vPosition.z;
      Dst.flt_10 = 0.0;
      Dst.flt_14 = 0.0;
      Dst.flt_18 = 0.0;
      if ( v10 & 0x200 )
      {
        Dst.type = ParticleType_Bitmap | ParticleType_Rotating | ParticleType_8;
        Dst.uDiffuse = 0xFF3C1E;
        Dst.flt_28 = 1.0;
        v11 = rand();
        v33 = (TEXTURE_TYPE)v8;
        v31 = "effpar01";
      }
      else
      {
        if ( v10 & 0x400 )
        {
          Dst.type = ParticleType_Line;
          Dst.uDiffuse = rand();
          Dst.timeToLive = 64;
          Dst.uTextureID = v8;
          Dst.flt_28 = 1.0;
          pGame->pParticleEngine->AddParticle(&Dst);
          return;
        }
        Dst.type = ParticleType_Bitmap | ParticleType_8;
        Dst.uDiffuse = rand();
        Dst.flt_28 = 1.0;
        v11 = rand();
        v33 = (TEXTURE_TYPE)v8;
        v31 = "effpar03";
      }
      Dst.timeToLive = (unsigned __int8)(v11 & 0x80) + 128;
      Dst.uTextureID = pBitmaps_LOD->LoadTexture(v31, v33);
      pGame->pParticleEngine->AddParticle(&Dst);
      return;
    }
    goto LABEL_25;
  }
}
// 46DF1A: using guessed type int __fastcall 46DF1A_collide_against_actor(int, int);

//----- (00438E35) --------------------------------------------------------
void SpriteObject::_438E35()
{
  SpriteObject *v1; // edi@1
  MapInfo *pMapInfo; // esi@1
  int v3; // ebx@1
  int v4; // eax@1
  int v5; // ebx@1
  unsigned int v6; // ecx@1
  int v7; // edx@2
  unsigned int v8; // edx@4
  unsigned int v9; // edx@6
  unsigned int v10; // eax@7
  signed int v11; // ebx@8
  Player **v12; // esi@18
  signed int v13; // edi@20
  int v15; // [sp+Ch] [bp-Ch]@1
  int v16; // [sp+10h] [bp-8h]@1
  signed int v17; // [sp+14h] [bp-4h]@8
  int v18; // [sp+14h] [bp-4h]@14

  v1 = this;
  pMapInfo = &pMapStats->pInfos[pMapStats->GetMapInfo(pCurrentMapName)];
  v3 = abs(pParty->vPosition.x - v1->vPosition.x);
  v15 = abs(pParty->vPosition.y - v1->vPosition.y);
  v16 = abs(pParty->vPosition.z + pParty->sEyelevel - v1->vPosition.z);
  v4 = v3;
  v5 = v15;
  v6 = v16;
  if ( v4 < v15 )
  {
    v7 = v4;
    v4 = v15;
    v5 = v7;
  }
  if ( v4 < v16 )
  {
    v8 = v4;
    v4 = v16;
    v6 = v8;
  }
  if ( v5 < (signed int)v6 )
  {
    v9 = v6;
    v6 = v5;
    v5 = v9;
  }
  v10 = ((unsigned int)(11 * v5) >> 5) + (v6 >> 2) + v4;
  if ( (signed int)v10 <= 768 )
  {
    v17 = 0;
    v11 = 5;
    if ( pMapInfo->Trap_D20 )
    {
      do
      {
        ++v17;
        v11 += rand() % 20 + 1;
      }
      while ( v17 < pMapInfo->Trap_D20 );
    }
    switch ( v1->uType )
    {
      case 0x32Bu:
        v18 = 0;
        break;
      case 0x32Cu:
        v18 = 1;
        break;
      case 0x32Du:
        v18 = 2;
        break;
      default:
        //LOWORD(v10) = v1->uItemType - 814;
        if ( v1->uType != 814 )
          return;
        v18 = 8;
        break;
    }
    v12 = &pPlayers[1];
    do
    {
      if ( (*v12)->CanAct() && (v13 = (*v12)->GetPerception() + 20, rand() % v13 > 20) )
        (*v12)->PlaySound(SPEECH_6, 0);
      else
        (*v12)->ReceiveDamage(v11, v18);
      ++v12;
    }
    while ( (signed int)v12 <= (signed int)&pPlayers[4] );
  }
}

//----- (0042F933) --------------------------------------------------------
void SpriteObject::OnInteraction(unsigned int uLayingItemID)
{
  pSpriteObjects[uLayingItemID].uObjectDescID = 0;
  if ( pParty->bTurnBasedModeOn == 1 )
  {
    if (pSpriteObjects[uLayingItemID].uAttributes & 4 )
    {
      pSpriteObjects[uLayingItemID].uAttributes &= 0xFB;
      --pTurnEngine->field_1C;
    }
  }
}


//----- (0042FA22) --------------------------------------------------------
void CompactLayingItemsList()
    {
    int new_obj_pos=0;

    for (int i=0; i<MAX_SPRITE_OBJECTS; ++i)
        {
        if (pSpriteObjects[i].uObjectDescID)
            memcpy(&pSpriteObjects[new_obj_pos++], &pSpriteObjects[i],sizeof(SpriteObject));
        }
    uNumSpriteObjects = new_obj_pos;
    }