mirror of
https://github.com/TombEngine/TombEngine.git
synced 2025-05-08 03:28:03 +03:00
Merge branch 'master' into renderer_refactor
This commit is contained in:
commit
9c48aa227b
19 changed files with 1292 additions and 1076 deletions
|
@ -558,7 +558,6 @@ void LaraGun(ITEM_INFO* laraItem)
|
|||
if (!GetAmmo(laraItem, laraInfo->gunType))
|
||||
{
|
||||
laraInfo->requestGunType = Objects[ID_PISTOLS_ITEM].loaded ? WEAPON_PISTOLS : WEAPON_NONE;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -635,7 +634,6 @@ void LaraGun(ITEM_INFO* laraItem)
|
|||
Ammo& GetAmmo(ITEM_INFO* lara, int weaponType)
|
||||
{
|
||||
LaraInfo*& laraInfo = lara->data;
|
||||
|
||||
return laraInfo->Weapons[weaponType].Ammo[laraInfo->Weapons[weaponType].SelectedAmmo];
|
||||
}
|
||||
|
||||
|
|
|
@ -34,73 +34,73 @@ using namespace TEN::Effects::Environment;
|
|||
|
||||
void FireHarpoon()
|
||||
{
|
||||
Ammo& ammos = GetAmmo(LaraItem, WEAPON_CROSSBOW);
|
||||
if (ammos.getCount() != 0)
|
||||
Ammo& ammos = GetAmmo(LaraItem, WEAPON_HARPOON_GUN);
|
||||
if (!ammos)
|
||||
return;
|
||||
|
||||
Lara.hasFired = true;
|
||||
|
||||
// Create a new item for harpoon
|
||||
short itemNumber = CreateItem();
|
||||
if (itemNumber != NO_ITEM)
|
||||
{
|
||||
Lara.hasFired = true;
|
||||
if (!ammos.hasInfinite())
|
||||
(ammos)--;
|
||||
|
||||
// Create a new item for harpoon
|
||||
short itemNumber = CreateItem();
|
||||
if (itemNumber != NO_ITEM)
|
||||
GAME_VECTOR pos;
|
||||
ITEM_INFO* item = &g_Level.Items[itemNumber];
|
||||
|
||||
item->shade = 0x4210 | 0x8000;
|
||||
item->objectNumber = ID_HARPOON;
|
||||
item->roomNumber = LaraItem->roomNumber;
|
||||
|
||||
PHD_VECTOR jointPos;
|
||||
|
||||
jointPos.x = -2;
|
||||
jointPos.y = 273 + 100;
|
||||
jointPos.z = 77;
|
||||
|
||||
GetLaraJointPosition(&jointPos, LM_RHAND);
|
||||
|
||||
FLOOR_INFO* floor = GetFloor(jointPos.x, jointPos.y, jointPos.z, &item->roomNumber);
|
||||
int height = GetFloorHeight(floor, jointPos.x, jointPos.y, jointPos.z);
|
||||
|
||||
if (height >= jointPos.y)
|
||||
{
|
||||
if (!ammos.hasInfinite())
|
||||
(ammos)--;
|
||||
|
||||
GAME_VECTOR pos;
|
||||
ITEM_INFO* item = &g_Level.Items[itemNumber];
|
||||
|
||||
item->shade = 0x4210 | 0x8000;
|
||||
item->objectNumber = ID_HARPOON;
|
||||
item->roomNumber = LaraItem->roomNumber;
|
||||
|
||||
PHD_VECTOR jointPos;
|
||||
|
||||
jointPos.x = -2;
|
||||
jointPos.y = 273 + 100;
|
||||
jointPos.z = 77;
|
||||
|
||||
GetLaraJointPosition(&jointPos, LM_RHAND);
|
||||
|
||||
FLOOR_INFO* floor = GetFloor(jointPos.x, jointPos.y, jointPos.z, &item->roomNumber);
|
||||
int height = GetFloorHeight(floor, jointPos.x, jointPos.y, jointPos.z);
|
||||
|
||||
if (height >= jointPos.y)
|
||||
{
|
||||
item->pos.xPos = jointPos.x;
|
||||
item->pos.yPos = jointPos.y;
|
||||
item->pos.zPos = jointPos.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->pos.xPos = LaraItem->pos.xPos;
|
||||
item->pos.yPos = jointPos.y;
|
||||
item->pos.zPos = LaraItem->pos.zPos;
|
||||
item->roomNumber = LaraItem->roomNumber;
|
||||
}
|
||||
|
||||
InitialiseItem(itemNumber);
|
||||
|
||||
item->pos.xRot = Lara.leftArm.xRot + LaraItem->pos.xRot;
|
||||
item->pos.zRot = 0;
|
||||
item->pos.yRot = Lara.leftArm.yRot + LaraItem->pos.yRot;
|
||||
|
||||
if (!Lara.leftArm.lock)
|
||||
{
|
||||
item->pos.xRot += Lara.torsoXrot;
|
||||
item->pos.yRot += Lara.torsoYrot;
|
||||
}
|
||||
|
||||
item->pos.zRot = 0;
|
||||
|
||||
item->fallspeed = -HARPOON_SPEED * phd_sin(item->pos.xRot);
|
||||
item->speed = HARPOON_SPEED * phd_cos(item->pos.xRot);
|
||||
item->hitPoints = HARPOON_TIME;
|
||||
|
||||
AddActiveItem(itemNumber);
|
||||
|
||||
Statistics.Level.AmmoUsed++;
|
||||
Statistics.Game.AmmoUsed++;
|
||||
item->pos.xPos = jointPos.x;
|
||||
item->pos.yPos = jointPos.y;
|
||||
item->pos.zPos = jointPos.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->pos.xPos = LaraItem->pos.xPos;
|
||||
item->pos.yPos = jointPos.y;
|
||||
item->pos.zPos = LaraItem->pos.zPos;
|
||||
item->roomNumber = LaraItem->roomNumber;
|
||||
}
|
||||
|
||||
InitialiseItem(itemNumber);
|
||||
|
||||
item->pos.xRot = Lara.leftArm.xRot + LaraItem->pos.xRot;
|
||||
item->pos.zRot = 0;
|
||||
item->pos.yRot = Lara.leftArm.yRot + LaraItem->pos.yRot;
|
||||
|
||||
if (!Lara.leftArm.lock)
|
||||
{
|
||||
item->pos.xRot += Lara.torsoXrot;
|
||||
item->pos.yRot += Lara.torsoYrot;
|
||||
}
|
||||
|
||||
item->pos.zRot = 0;
|
||||
|
||||
item->fallspeed = -HARPOON_SPEED * phd_sin(item->pos.xRot);
|
||||
item->speed = HARPOON_SPEED * phd_cos(item->pos.xRot);
|
||||
item->hitPoints = HARPOON_TIME;
|
||||
|
||||
AddActiveItem(itemNumber);
|
||||
|
||||
Statistics.Level.AmmoUsed++;
|
||||
Statistics.Game.AmmoUsed++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,77 +114,47 @@ void HarpoonBoltControl(short itemNumber)
|
|||
int oldZ = item->pos.zPos;
|
||||
short roomNumber = item->roomNumber;
|
||||
|
||||
/*if (item->pos.yPos >= item->floor || item->pos.yPos <= GetCeiling(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos))
|
||||
{
|
||||
if (item->hitPoints == HARPOON_TIME)
|
||||
{
|
||||
item->currentAnimState = item->pos.xRot;
|
||||
}
|
||||
bool aboveWater = false;
|
||||
|
||||
if (item->hitPoints >= 192)
|
||||
{
|
||||
item->pos.xRot = item->currentAnimState + ((((phd_sin(item->hitPoints * 2048) / 8) - 1024) * (item->hitPoints - 192)) / 64);
|
||||
item->hitPoints--;
|
||||
}
|
||||
// Update speed and check if above water
|
||||
|
||||
item->hitPoints--;
|
||||
if (!item->hitPoints)
|
||||
{
|
||||
KillItem(itemNumber);
|
||||
return;
|
||||
}
|
||||
item->speed = item->fallspeed = 0;
|
||||
}
|
||||
else
|
||||
if (item->hitPoints == HARPOON_TIME)
|
||||
{
|
||||
item->pos.zRot += ANGLE(35);
|
||||
if (!(g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_WATER))
|
||||
{
|
||||
item->pos.xRot -= (ANGLE(1));
|
||||
item->pos.xRot -= ANGLE(1);
|
||||
if (item->pos.xRot < -ANGLE(90))
|
||||
item->pos.xRot = -ANGLE(90);
|
||||
item->fallspeed = (short)(-HARPOON_SPEED * phd_sin(item->pos.xRot) >> W2V_SHIFT);
|
||||
item->speed = (short)(HARPOON_SPEED * phd_cos(item->pos.xRot) >> W2V_SHIFT);
|
||||
item->fallspeed = -HARPOON_SPEED * phd_sin(item->pos.xRot);
|
||||
item->speed = HARPOON_SPEED * phd_cos(item->pos.xRot);
|
||||
aboveWater = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create bubbles
|
||||
if ((Wibble & 15) == 0)
|
||||
CreateBubble((PHD_VECTOR*)&item->pos, item->roomNumber, 2, 8);
|
||||
CreateBubble((PHD_VECTOR*)&item->pos, item->roomNumber, 0, 0, BUBBLE_FLAG_CLUMP | BUBBLE_FLAG_HIGH_AMPLITUDE, 0, 0, 0); // CHECK
|
||||
TriggerRocketSmoke(item->pos.xPos, item->pos.yPos, item->pos.zPos, 64);
|
||||
item->fallspeed = (short)(-(HARPOON_SPEED >> 1) * phd_sin(item->pos.xRot) >> W2V_SHIFT);
|
||||
item->speed = (short)((HARPOON_SPEED >> 1) * phd_cos(item->pos.xRot) >> W2V_SHIFT);
|
||||
item->fallspeed = -HARPOON_SPEED * phd_sin(item->pos.xRot) / 2;
|
||||
item->speed = HARPOON_SPEED * phd_cos(item->pos.xRot) / 2;
|
||||
aboveWater = false;
|
||||
}
|
||||
}*/
|
||||
|
||||
bool aboveWater = false;
|
||||
|
||||
// Update speed and check if above water
|
||||
item->pos.zRot += ANGLE(35);
|
||||
if (!(g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_WATER))
|
||||
{
|
||||
item->pos.xRot -= ANGLE(1);
|
||||
if (item->pos.xRot < -16384)
|
||||
item->pos.xRot = -16384;
|
||||
item->fallspeed = -HARPOON_SPEED * phd_sin(item->pos.xRot);
|
||||
item->speed = HARPOON_SPEED * phd_cos(item->pos.xRot);
|
||||
aboveWater = true;
|
||||
// Update bolt's position
|
||||
item->pos.xPos += item->speed * phd_cos(item->pos.xRot) * phd_sin(item->pos.yRot);
|
||||
item->pos.yPos += item->speed * phd_sin(-item->pos.xRot);
|
||||
item->pos.zPos += item->speed * phd_cos(item->pos.xRot) * phd_cos(item->pos.yRot);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create bubbles
|
||||
if ((Wibble & 15) == 0)
|
||||
CreateBubble((PHD_VECTOR*)& item->pos, item->roomNumber, 0, 0, BUBBLE_FLAG_CLUMP | BUBBLE_FLAG_HIGH_AMPLITUDE, 0, 0, 0); // CHECK
|
||||
TriggerRocketSmoke(item->pos.xPos, item->pos.yPos, item->pos.zPos, 64);
|
||||
item->fallspeed = -HARPOON_SPEED * phd_sin(item->pos.xRot) / 2;
|
||||
item->speed = HARPOON_SPEED * phd_cos(item->pos.xRot) / 2;
|
||||
aboveWater = false;
|
||||
if (item->hitPoints > 0)
|
||||
item->hitPoints--;
|
||||
else
|
||||
KillItem(itemNumber);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update bolt's position
|
||||
item->pos.xPos += item->speed * phd_cos(item->pos.xRot) * phd_sin(item->pos.yRot);
|
||||
item->pos.yPos += item->speed * phd_sin(-item->pos.xRot);
|
||||
item->pos.zPos += item->speed * phd_cos(item->pos.xRot) * phd_cos(item->pos.yRot);
|
||||
|
||||
roomNumber = item->roomNumber;
|
||||
FLOOR_INFO * floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
|
||||
|
||||
|
@ -193,12 +163,7 @@ void HarpoonBoltControl(short itemNumber)
|
|||
GetCeiling(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos) > item->pos.yPos)
|
||||
{
|
||||
// I have hit a solid wall, this is the end for the bolt
|
||||
item->pos.xPos = oldX;
|
||||
item->pos.yPos = oldY;
|
||||
item->pos.zPos = oldZ;
|
||||
|
||||
ExplodeItemNode(item, 0, 0, EXPLODE_NORMAL);
|
||||
KillItem(itemNumber);
|
||||
item->hitPoints--;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -222,8 +187,6 @@ void HarpoonBoltControl(short itemNumber)
|
|||
if (!CollidedItems[0] && !CollidedMeshes[0])
|
||||
return;
|
||||
|
||||
foundCollidedObjects = true;
|
||||
|
||||
if (CollidedItems[0])
|
||||
{
|
||||
ITEM_INFO* currentItem = CollidedItems[0];
|
||||
|
@ -233,13 +196,13 @@ void HarpoonBoltControl(short itemNumber)
|
|||
{
|
||||
OBJECT_INFO* currentObj = &Objects[currentItem->objectNumber];
|
||||
|
||||
if (!currentObj->isPickup && currentObj->collision && currentItem->collidable)
|
||||
foundCollidedObjects = true;
|
||||
|
||||
if (currentObj->intelligent && currentObj->collision && currentItem->status == ITEM_ACTIVE && !currentObj->undead)
|
||||
{
|
||||
HitTarget(LaraItem, currentItem, (GAME_VECTOR*)&item->pos, Weapons[WEAPON_HARPOON_GUN].damage, 0);
|
||||
}
|
||||
|
||||
// All other items (like puzzles) can't be hit
|
||||
|
||||
k++;
|
||||
currentItem = CollidedItems[k];
|
||||
|
||||
|
@ -293,86 +256,86 @@ void FireGrenade()
|
|||
int z = 0;
|
||||
|
||||
Ammo& ammo = GetAmmo(LaraItem, WEAPON_GRENADE_LAUNCHER);
|
||||
if (ammo != size_t{ 0 })
|
||||
if (!ammo)
|
||||
return;
|
||||
|
||||
Lara.hasFired = true;
|
||||
|
||||
short itemNumber = CreateItem();
|
||||
if (itemNumber != NO_ITEM)
|
||||
{
|
||||
Lara.hasFired = true;
|
||||
ITEM_INFO* item = &g_Level.Items[itemNumber];
|
||||
|
||||
item->shade = 0xC210;
|
||||
item->objectNumber = ID_GRENADE;
|
||||
item->roomNumber = LaraItem->roomNumber;
|
||||
|
||||
short itemNumber = CreateItem();
|
||||
if (itemNumber != NO_ITEM)
|
||||
PHD_VECTOR jointPos;
|
||||
jointPos.x = 0;
|
||||
jointPos.y = 276;
|
||||
jointPos.z = 80;
|
||||
|
||||
GetLaraJointPosition(&jointPos, LM_RHAND);
|
||||
|
||||
item->pos.xPos = x = jointPos.x;
|
||||
item->pos.yPos = y = jointPos.y;
|
||||
item->pos.zPos = z = jointPos.z;
|
||||
|
||||
FLOOR_INFO* floor = GetFloor(jointPos.x, jointPos.y, jointPos.z, &item->roomNumber);
|
||||
int height = GetFloorHeight(floor, jointPos.x, jointPos.y, jointPos.z);
|
||||
if (height < jointPos.y)
|
||||
{
|
||||
ITEM_INFO* item = &g_Level.Items[itemNumber];
|
||||
|
||||
item->shade = 0xC210;
|
||||
item->objectNumber = ID_GRENADE;
|
||||
item->pos.xPos = LaraItem->pos.xPos;
|
||||
item->pos.yPos = jointPos.y;
|
||||
item->pos.zPos = LaraItem->pos.zPos;
|
||||
item->roomNumber = LaraItem->roomNumber;
|
||||
|
||||
PHD_VECTOR jointPos;
|
||||
jointPos.x = 0;
|
||||
jointPos.y = 276;
|
||||
jointPos.z = 80;
|
||||
|
||||
GetLaraJointPosition(&jointPos, LM_RHAND);
|
||||
|
||||
item->pos.xPos = x = jointPos.x;
|
||||
item->pos.yPos = y = jointPos.y;
|
||||
item->pos.zPos = z = jointPos.z;
|
||||
|
||||
FLOOR_INFO* floor = GetFloor(jointPos.x, jointPos.y, jointPos.z, &item->roomNumber);
|
||||
int height = GetFloorHeight(floor, jointPos.x, jointPos.y, jointPos.z);
|
||||
if (height < jointPos.y)
|
||||
{
|
||||
item->pos.xPos = LaraItem->pos.xPos;
|
||||
item->pos.yPos = jointPos.y;
|
||||
item->pos.zPos = LaraItem->pos.zPos;
|
||||
item->roomNumber = LaraItem->roomNumber;
|
||||
}
|
||||
|
||||
jointPos.x = 0;
|
||||
jointPos.y = 1204;
|
||||
jointPos.z = 5;
|
||||
|
||||
GetLaraJointPosition(&jointPos, LM_RHAND);
|
||||
|
||||
SmokeCountL = 32;
|
||||
SmokeWeapon = WEAPON_GRENADE_LAUNCHER;
|
||||
|
||||
if (LaraItem->meshBits)
|
||||
{
|
||||
for (int i = 0; i < 5; i++)
|
||||
TriggerGunSmoke(x, y, z, jointPos.x - x, jointPos.y - y, jointPos.z - z, 1, WEAPON_GRENADE_LAUNCHER, 32);
|
||||
|
||||
}
|
||||
|
||||
InitialiseItem(itemNumber);
|
||||
|
||||
item->pos.xRot = LaraItem->pos.xRot + Lara.leftArm.xRot;
|
||||
item->pos.yRot = LaraItem->pos.yRot + Lara.leftArm.yRot;
|
||||
item->pos.zRot = 0;
|
||||
|
||||
if (!Lara.leftArm.lock)
|
||||
{
|
||||
item->pos.xRot += Lara.torsoXrot;
|
||||
item->pos.yRot += Lara.torsoYrot;
|
||||
}
|
||||
|
||||
item->speed = GRENADE_SPEED;
|
||||
item->fallspeed = -512 * phd_sin(item->pos.xRot);
|
||||
item->currentAnimState = item->pos.xRot;
|
||||
item->goalAnimState = item->pos.yRot;
|
||||
item->requiredAnimState = 0;
|
||||
item->hitPoints = 120;
|
||||
item->itemFlags[0] = WEAPON_AMMO2;
|
||||
|
||||
AddActiveItem(itemNumber);
|
||||
|
||||
if (!ammo.hasInfinite())
|
||||
(ammo)--;
|
||||
|
||||
item->itemFlags[0] = Lara.Weapons[WEAPON_GRENADE_LAUNCHER].SelectedAmmo;
|
||||
|
||||
Statistics.Level.AmmoUsed++;
|
||||
Statistics.Game.AmmoUsed++;
|
||||
}
|
||||
|
||||
jointPos.x = 0;
|
||||
jointPos.y = 1204;
|
||||
jointPos.z = 5;
|
||||
|
||||
GetLaraJointPosition(&jointPos, LM_RHAND);
|
||||
|
||||
SmokeCountL = 32;
|
||||
SmokeWeapon = WEAPON_GRENADE_LAUNCHER;
|
||||
|
||||
if (LaraItem->meshBits)
|
||||
{
|
||||
for (int i = 0; i < 5; i++)
|
||||
TriggerGunSmoke(x, y, z, jointPos.x - x, jointPos.y - y, jointPos.z - z, 1, WEAPON_GRENADE_LAUNCHER, 32);
|
||||
|
||||
}
|
||||
|
||||
InitialiseItem(itemNumber);
|
||||
|
||||
item->pos.xRot = LaraItem->pos.xRot + Lara.leftArm.xRot;
|
||||
item->pos.yRot = LaraItem->pos.yRot + Lara.leftArm.yRot;
|
||||
item->pos.zRot = 0;
|
||||
|
||||
if (!Lara.leftArm.lock)
|
||||
{
|
||||
item->pos.xRot += Lara.torsoXrot;
|
||||
item->pos.yRot += Lara.torsoYrot;
|
||||
}
|
||||
|
||||
item->speed = GRENADE_SPEED;
|
||||
item->fallspeed = -512 * phd_sin(item->pos.xRot);
|
||||
item->currentAnimState = item->pos.xRot;
|
||||
item->goalAnimState = item->pos.yRot;
|
||||
item->requiredAnimState = 0;
|
||||
item->hitPoints = 120;
|
||||
item->itemFlags[0] = WEAPON_AMMO2;
|
||||
|
||||
AddActiveItem(itemNumber);
|
||||
|
||||
if (!ammo.hasInfinite())
|
||||
(ammo)--;
|
||||
|
||||
item->itemFlags[0] = Lara.Weapons[WEAPON_GRENADE_LAUNCHER].SelectedAmmo;
|
||||
|
||||
Statistics.Level.AmmoUsed++;
|
||||
Statistics.Game.AmmoUsed++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1556,84 +1519,84 @@ void RifleHandler(int weaponType)
|
|||
void FireCrossbow(PHD_3DPOS* pos)
|
||||
{
|
||||
Ammo& ammos = GetAmmo(LaraItem, WEAPON_CROSSBOW);
|
||||
if (ammos)
|
||||
if (!ammos)
|
||||
return;
|
||||
|
||||
Lara.hasFired = true;
|
||||
|
||||
short itemNumber = CreateItem();
|
||||
if (itemNumber != NO_ITEM)
|
||||
{
|
||||
Lara.hasFired = true;
|
||||
|
||||
short itemNumber = CreateItem();
|
||||
if (itemNumber != NO_ITEM)
|
||||
ITEM_INFO* item = &g_Level.Items[itemNumber];
|
||||
item->objectNumber = ID_CROSSBOW_BOLT;
|
||||
item->shade = 0xC210;
|
||||
if (!ammos.hasInfinite())
|
||||
(ammos)--;
|
||||
if (pos)
|
||||
{
|
||||
ITEM_INFO* item = &g_Level.Items[itemNumber];
|
||||
item->objectNumber = ID_CROSSBOW_BOLT;
|
||||
item->shade = 0xC210;
|
||||
if (!ammos.hasInfinite())
|
||||
(ammos)--;
|
||||
if (pos)
|
||||
item->roomNumber = LaraItem->roomNumber;
|
||||
item->pos.xPos = pos->xPos;
|
||||
item->pos.yPos = pos->yPos;
|
||||
item->pos.zPos = pos->zPos;
|
||||
|
||||
InitialiseItem(itemNumber);
|
||||
|
||||
item->pos.xRot = pos->xRot;
|
||||
item->pos.yRot = pos->yRot;
|
||||
item->pos.zRot = pos->zRot;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
PHD_VECTOR jointPos;
|
||||
jointPos.x = 0;
|
||||
jointPos.y = 228;
|
||||
jointPos.z = 32;
|
||||
|
||||
GetLaraJointPosition(&jointPos, LM_RHAND);
|
||||
|
||||
item->roomNumber = LaraItem->roomNumber;
|
||||
|
||||
FLOOR_INFO * floor = GetFloor(jointPos.x, jointPos.y, jointPos.z, &item->roomNumber);
|
||||
int height = GetFloorHeight(floor, jointPos.x, jointPos.y, jointPos.z);
|
||||
|
||||
if (height >= jointPos.y)
|
||||
{
|
||||
item->roomNumber = LaraItem->roomNumber;
|
||||
item->pos.xPos = pos->xPos;
|
||||
item->pos.yPos = pos->yPos;
|
||||
item->pos.zPos = pos->zPos;
|
||||
|
||||
InitialiseItem(itemNumber);
|
||||
|
||||
item->pos.xRot = pos->xRot;
|
||||
item->pos.yRot = pos->yRot;
|
||||
item->pos.zRot = pos->zRot;
|
||||
item->pos.xPos = jointPos.x;
|
||||
item->pos.yPos = jointPos.y;
|
||||
item->pos.zPos = jointPos.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
PHD_VECTOR jointPos;
|
||||
jointPos.x = 0;
|
||||
jointPos.y = 228;
|
||||
jointPos.z = 32;
|
||||
|
||||
GetLaraJointPosition(&jointPos, LM_RHAND);
|
||||
|
||||
item->pos.xPos = LaraItem->pos.xPos;
|
||||
item->pos.yPos = jointPos.y;
|
||||
item->pos.zPos = LaraItem->pos.zPos;
|
||||
item->roomNumber = LaraItem->roomNumber;
|
||||
|
||||
FLOOR_INFO * floor = GetFloor(jointPos.x, jointPos.y, jointPos.z, &item->roomNumber);
|
||||
int height = GetFloorHeight(floor, jointPos.x, jointPos.y, jointPos.z);
|
||||
|
||||
if (height >= jointPos.y)
|
||||
{
|
||||
item->pos.xPos = jointPos.x;
|
||||
item->pos.yPos = jointPos.y;
|
||||
item->pos.zPos = jointPos.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->pos.xPos = LaraItem->pos.xPos;
|
||||
item->pos.yPos = jointPos.y;
|
||||
item->pos.zPos = LaraItem->pos.zPos;
|
||||
item->roomNumber = LaraItem->roomNumber;
|
||||
}
|
||||
|
||||
InitialiseItem(itemNumber);
|
||||
|
||||
item->pos.xRot = Lara.leftArm.xRot + LaraItem->pos.xRot;
|
||||
item->pos.zRot = 0;
|
||||
item->pos.yRot = Lara.leftArm.yRot + LaraItem->pos.yRot;
|
||||
|
||||
if (!Lara.leftArm.lock)
|
||||
{
|
||||
item->pos.xRot += Lara.torsoXrot;
|
||||
item->pos.yRot += Lara.torsoYrot;
|
||||
}
|
||||
}
|
||||
|
||||
item->speed = 512;
|
||||
InitialiseItem(itemNumber);
|
||||
|
||||
AddActiveItem(itemNumber);
|
||||
item->pos.xRot = Lara.leftArm.xRot + LaraItem->pos.xRot;
|
||||
item->pos.zRot = 0;
|
||||
item->pos.yRot = Lara.leftArm.yRot + LaraItem->pos.yRot;
|
||||
|
||||
item->itemFlags[0] = Lara.Weapons[WEAPON_CROSSBOW].SelectedAmmo;
|
||||
|
||||
SoundEffect(SFX_TR4_LARA_CROSSBOW, 0, 0);
|
||||
|
||||
Statistics.Level.AmmoUsed++;
|
||||
Statistics.Game.AmmoUsed++;
|
||||
if (!Lara.leftArm.lock)
|
||||
{
|
||||
item->pos.xRot += Lara.torsoXrot;
|
||||
item->pos.yRot += Lara.torsoYrot;
|
||||
}
|
||||
}
|
||||
|
||||
item->speed = 512;
|
||||
|
||||
AddActiveItem(itemNumber);
|
||||
|
||||
item->itemFlags[0] = Lara.Weapons[WEAPON_CROSSBOW].SelectedAmmo;
|
||||
|
||||
SoundEffect(SFX_TR4_LARA_CROSSBOW, 0, 0);
|
||||
|
||||
Statistics.Level.AmmoUsed++;
|
||||
Statistics.Game.AmmoUsed++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1663,74 +1626,75 @@ void FireCrossBowFromLaserSight(GAME_VECTOR* src, GAME_VECTOR* target)
|
|||
void FireRocket()
|
||||
{
|
||||
Ammo& ammos = GetAmmo(LaraItem, WEAPON_ROCKET_LAUNCHER);
|
||||
if (ammos) {
|
||||
Lara.hasFired = true;
|
||||
if (!ammos)
|
||||
return;
|
||||
|
||||
short itemNumber = CreateItem();
|
||||
if (itemNumber != NO_ITEM)
|
||||
Lara.hasFired = true;
|
||||
|
||||
short itemNumber = CreateItem();
|
||||
if (itemNumber != NO_ITEM)
|
||||
{
|
||||
ITEM_INFO* item = &g_Level.Items[itemNumber];
|
||||
item->objectNumber = ID_ROCKET;
|
||||
item->roomNumber = LaraItem->roomNumber;
|
||||
|
||||
if (!ammos.hasInfinite())
|
||||
(ammos)--;
|
||||
|
||||
PHD_VECTOR jointPos;
|
||||
jointPos.x = 0;
|
||||
jointPos.y = 180;
|
||||
jointPos.z = 72;
|
||||
|
||||
GetLaraJointPosition(&jointPos, LM_RHAND);
|
||||
|
||||
int x, y, z;
|
||||
item->pos.xPos = x = jointPos.x;
|
||||
item->pos.yPos = y = jointPos.y;
|
||||
item->pos.zPos = z = jointPos.z;
|
||||
|
||||
jointPos.x = 0;
|
||||
jointPos.y = 180 + 1024;
|
||||
jointPos.z = 72;
|
||||
|
||||
GetLaraJointPosition(&jointPos, LM_RHAND);
|
||||
|
||||
SmokeCountL = 32;
|
||||
SmokeWeapon = WEAPON_ROCKET_LAUNCHER;
|
||||
|
||||
for(int i = 0; i < 5; i++)
|
||||
TriggerGunSmoke(x, y, z, jointPos.x - x, jointPos.y - y, jointPos.z - z, 1, WEAPON_ROCKET_LAUNCHER, 32);
|
||||
|
||||
jointPos.x = 0;
|
||||
jointPos.y = -256;
|
||||
jointPos.z = 0;
|
||||
|
||||
GetLaraJointPosition(&jointPos, LM_RHAND);
|
||||
|
||||
for(int i = 0; i < 10; i++)
|
||||
TriggerGunSmoke(jointPos.x, jointPos.y, jointPos.z, jointPos.x - x, jointPos.y - y, jointPos.z - z, 2, WEAPON_ROCKET_LAUNCHER, 32);
|
||||
|
||||
InitialiseItem(itemNumber);
|
||||
|
||||
item->pos.xRot = LaraItem->pos.xRot + Lara.leftArm.xRot;
|
||||
item->pos.yRot = LaraItem->pos.yRot + Lara.leftArm.yRot;
|
||||
item->pos.zRot = 0;
|
||||
|
||||
if (!Lara.leftArm.lock)
|
||||
{
|
||||
ITEM_INFO* item = &g_Level.Items[itemNumber];
|
||||
item->objectNumber = ID_ROCKET;
|
||||
item->roomNumber = LaraItem->roomNumber;
|
||||
|
||||
if (!ammos.hasInfinite())
|
||||
(ammos)--;
|
||||
|
||||
PHD_VECTOR jointPos;
|
||||
jointPos.x = 0;
|
||||
jointPos.y = 180;
|
||||
jointPos.z = 72;
|
||||
|
||||
GetLaraJointPosition(&jointPos, LM_RHAND);
|
||||
|
||||
int x, y, z;
|
||||
item->pos.xPos = x = jointPos.x;
|
||||
item->pos.yPos = y = jointPos.y;
|
||||
item->pos.zPos = z = jointPos.z;
|
||||
|
||||
jointPos.x = 0;
|
||||
jointPos.y = 180 + 1024;
|
||||
jointPos.z = 72;
|
||||
|
||||
GetLaraJointPosition(&jointPos, LM_RHAND);
|
||||
|
||||
SmokeCountL = 32;
|
||||
SmokeWeapon = WEAPON_ROCKET_LAUNCHER;
|
||||
|
||||
for(int i = 0; i < 5; i++)
|
||||
TriggerGunSmoke(x, y, z, jointPos.x - x, jointPos.y - y, jointPos.z - z, 1, WEAPON_ROCKET_LAUNCHER, 32);
|
||||
|
||||
jointPos.x = 0;
|
||||
jointPos.y = -256;
|
||||
jointPos.z = 0;
|
||||
|
||||
GetLaraJointPosition(&jointPos, LM_RHAND);
|
||||
|
||||
for(int i = 0; i < 10; i++)
|
||||
TriggerGunSmoke(jointPos.x, jointPos.y, jointPos.z, jointPos.x - x, jointPos.y - y, jointPos.z - z, 2, WEAPON_ROCKET_LAUNCHER, 32);
|
||||
|
||||
InitialiseItem(itemNumber);
|
||||
|
||||
item->pos.xRot = LaraItem->pos.xRot + Lara.leftArm.xRot;
|
||||
item->pos.yRot = LaraItem->pos.yRot + Lara.leftArm.yRot;
|
||||
item->pos.zRot = 0;
|
||||
|
||||
if (!Lara.leftArm.lock)
|
||||
{
|
||||
item->pos.xRot += Lara.torsoXrot;
|
||||
item->pos.yRot += Lara.torsoYrot;
|
||||
}
|
||||
|
||||
item->speed = 512 >> 5;
|
||||
item->itemFlags[0] = 0;
|
||||
|
||||
AddActiveItem(itemNumber);
|
||||
|
||||
SoundEffect(SFX_TR4_EXPLOSION1, 0, 0);
|
||||
|
||||
Statistics.Level.AmmoUsed++;
|
||||
Statistics.Game.AmmoUsed++;
|
||||
item->pos.xRot += Lara.torsoXrot;
|
||||
item->pos.yRot += Lara.torsoYrot;
|
||||
}
|
||||
|
||||
item->speed = 512 >> 5;
|
||||
item->itemFlags[0] = 0;
|
||||
|
||||
AddActiveItem(itemNumber);
|
||||
|
||||
SoundEffect(SFX_TR4_EXPLOSION1, 0, 0);
|
||||
|
||||
Statistics.Level.AmmoUsed++;
|
||||
Statistics.Game.AmmoUsed++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ enum GRENADE_TYPE
|
|||
constexpr auto HARPOON_DRAW_ANIM = 1;
|
||||
constexpr auto ROCKET_DRAW_ANIM = 0;
|
||||
constexpr auto HARPOON_SPEED = 256;
|
||||
constexpr auto HARPOON_TIME = 256;
|
||||
constexpr auto HARPOON_TIME = 300;
|
||||
constexpr auto ROCKET_SPEED = 512;
|
||||
constexpr auto GRENADE_SPEED = 128;
|
||||
constexpr auto MAX_GRENADE_FALLSPEED = 128;
|
||||
|
|
|
@ -21,37 +21,46 @@ using namespace TEN::Floordata;
|
|||
// Test if a ledge in front of item is valid to climb.
|
||||
bool TestValidLedge(ITEM_INFO* item, COLL_INFO* coll, bool ignoreHeadroom, bool heightLimit)
|
||||
{
|
||||
// Determine probe base point.
|
||||
// We use 1/3 radius extents here for two purposes. First - we can't guarantee that
|
||||
// shifts weren't already applied and misfire may occur. Second - it guarantees
|
||||
// that Lara won't land on a very thin edge of diagonal geometry.
|
||||
|
||||
int xf = phd_sin(coll->NearestLedgeAngle) * (coll->Setup.Radius * 1.3f);
|
||||
int zf = phd_cos(coll->NearestLedgeAngle) * (coll->Setup.Radius * 1.3f);
|
||||
|
||||
// Determine probe left/right points
|
||||
int xl = xf + phd_sin(coll->NearestLedgeAngle - ANGLE(90)) * coll->Setup.Radius;
|
||||
int zl = zf + phd_cos(coll->NearestLedgeAngle - ANGLE(90)) * coll->Setup.Radius;
|
||||
int xr = xf + phd_sin(coll->NearestLedgeAngle + ANGLE(90)) * coll->Setup.Radius;
|
||||
int zr = zf + phd_cos(coll->NearestLedgeAngle + ANGLE(90)) * coll->Setup.Radius;
|
||||
// Determine probe base left/right points
|
||||
int xl = phd_sin(coll->NearestLedgeAngle - ANGLE(90)) * coll->Setup.Radius;
|
||||
int zl = phd_cos(coll->NearestLedgeAngle - ANGLE(90)) * coll->Setup.Radius;
|
||||
int xr = phd_sin(coll->NearestLedgeAngle + ANGLE(90)) * coll->Setup.Radius;
|
||||
int zr = phd_cos(coll->NearestLedgeAngle + ANGLE(90)) * coll->Setup.Radius;
|
||||
|
||||
// Determine probe top point
|
||||
int y = item->pos.yPos - coll->Setup.Height;
|
||||
|
||||
// Get floor heights at both points
|
||||
auto left = GetCollisionResult(item->pos.xPos + xl, y, item->pos.zPos + zl, GetRoom(item->location, item->pos.xPos, y, item->pos.zPos).roomNumber).Position.Floor;
|
||||
auto right = GetCollisionResult(item->pos.xPos + xr, y, item->pos.zPos + zr, GetRoom(item->location, item->pos.xPos, y, item->pos.zPos).roomNumber).Position.Floor;
|
||||
// Get frontal collision data
|
||||
auto frontLeft = GetCollisionResult(item->pos.xPos + xl, y, item->pos.zPos + zl, GetRoom(item->location, item->pos.xPos, y, item->pos.zPos).roomNumber);
|
||||
auto frontRight = GetCollisionResult(item->pos.xPos + xr, y, item->pos.zPos + zr, GetRoom(item->location, item->pos.xPos, y, item->pos.zPos).roomNumber);
|
||||
|
||||
// If any of the frontal collision results intersects item bounds, return false, because there is material intersection.
|
||||
// This check helps to filter out cases when Lara is formally facing corner but ledge check returns true because probe distance is fixed.
|
||||
if (frontLeft.Position.Floor < (item->pos.yPos - CLICK(0.5f)) || frontRight.Position.Floor < (item->pos.yPos - CLICK(0.5f)))
|
||||
return false;
|
||||
if (frontLeft.Position.Ceiling > (item->pos.yPos - coll->Setup.Height) || frontRight.Position.Ceiling > (item->pos.yPos - coll->Setup.Height))
|
||||
return false;
|
||||
|
||||
//g_Renderer.addDebugSphere(Vector3(item->pos.xPos + xl, left, item->pos.zPos + zl), 64, Vector4::One, RENDERER_DEBUG_PAGE::LOGIC_STATS);
|
||||
//g_Renderer.addDebugSphere(Vector3(item->pos.xPos + xr, right, item->pos.zPos + zr), 64, Vector4::One, RENDERER_DEBUG_PAGE::LOGIC_STATS);
|
||||
|
||||
// Determine ledge probe embed offset.
|
||||
// We use 0.2f radius extents here for two purposes. First - we can't guarantee that shifts weren't already applied
|
||||
// and misfire may occur. Second - it guarantees that Lara won't land on a very thin edge of diagonal geometry.
|
||||
int xf = phd_sin(coll->NearestLedgeAngle) * (coll->Setup.Radius * 1.2f);
|
||||
int zf = phd_cos(coll->NearestLedgeAngle) * (coll->Setup.Radius * 1.2f);
|
||||
|
||||
// Determine allowed slope difference for a given collision radius
|
||||
auto slopeDelta = ((float)STEPUP_HEIGHT / (float)WALL_SIZE) * (coll->Setup.Radius * 2);
|
||||
// Get floor heights at both points
|
||||
auto left = GetCollisionResult(item->pos.xPos + xf + xl, y, item->pos.zPos + zf + zl, GetRoom(item->location, item->pos.xPos, y, item->pos.zPos).roomNumber).Position.Floor;
|
||||
auto right = GetCollisionResult(item->pos.xPos + xf + xr, y, item->pos.zPos + zf + zr, GetRoom(item->location, item->pos.xPos, y, item->pos.zPos).roomNumber).Position.Floor;
|
||||
|
||||
// If specified, limit vertical search zone only to nearest height
|
||||
if (heightLimit && (abs(left - y) > (STEP_SIZE / 2) || abs(right - y) > (STEP_SIZE / 2)))
|
||||
return false;
|
||||
|
||||
// Determine allowed slope difference for a given collision radius
|
||||
auto slopeDelta = ((float)STEPUP_HEIGHT / (float)WALL_SIZE) * (coll->Setup.Radius * 2);
|
||||
|
||||
// Discard if there is a slope beyond tolerance delta
|
||||
if (abs(left - right) >= slopeDelta)
|
||||
return false;
|
||||
|
@ -514,7 +523,7 @@ bool TestLaraHang(ITEM_INFO* item, COLL_INFO* coll)
|
|||
item->pos.zPos += phd_cos(item->pos.yRot) * coll->Setup.Radius * 0.5f;
|
||||
|
||||
// Get height difference with side spaces (left or right, depending on movement direction)
|
||||
auto hdif = LaraFloorFront(item, Lara.moveAngle, coll->Setup.Radius * 1.5f);
|
||||
auto hdif = LaraFloorFront(item, Lara.moveAngle, coll->Setup.Radius * 1.4f);
|
||||
|
||||
// Set stopped flag, if floor height is above footspace which is step size
|
||||
auto stopped = hdif < STEP_SIZE / 2;
|
||||
|
@ -962,18 +971,17 @@ bool TestLaraHangSideways(ITEM_INFO* item, COLL_INFO* coll, short angle)
|
|||
{
|
||||
auto oldPos = item->pos;
|
||||
|
||||
Lara.moveAngle = item->pos.yRot + angle;
|
||||
|
||||
static constexpr auto sidewayTestDistance = 16;
|
||||
item->pos.xPos += phd_sin(Lara.moveAngle) * sidewayTestDistance;
|
||||
item->pos.zPos += phd_cos(Lara.moveAngle) * sidewayTestDistance;
|
||||
|
||||
Lara.moveAngle = item->pos.yRot + angle;
|
||||
|
||||
coll->Setup.OldPosition.y = item->pos.yPos;
|
||||
|
||||
auto res = TestLaraHang(item, coll);
|
||||
|
||||
item->pos = oldPos;
|
||||
Lara.moveAngle = item->pos.yRot + angle;
|
||||
|
||||
return !res;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "level.h"
|
||||
#include "setup.h"
|
||||
#include "collide.h"
|
||||
#include "room.h"
|
||||
#include "Sound/sound.h"
|
||||
#include "control/los.h"
|
||||
#include "savegame.h"
|
||||
|
@ -20,6 +21,11 @@ using TEN::Renderer::g_Renderer;
|
|||
using namespace TEN::Entities::Generic;
|
||||
using namespace TEN::Effects::Environment;
|
||||
|
||||
constexpr auto COLL_CHECK_THRESHOLD = SECTOR(4);
|
||||
constexpr auto COLL_CANCEL_THRESHOLD = SECTOR(2);
|
||||
constexpr auto COLL_DISCARD_THRESHOLD = CLICK(0.5f);
|
||||
constexpr auto CAMERA_RADIUS = CLICK(1);
|
||||
|
||||
struct OLD_CAMERA
|
||||
{
|
||||
short currentAnimState;
|
||||
|
@ -284,6 +290,8 @@ void MoveCamera(GAME_VECTOR* ideal, int speed)
|
|||
Camera.pos.roomNumber = ideal->roomNumber;
|
||||
}
|
||||
|
||||
ItemsCollideCamera();
|
||||
|
||||
GetFloor(Camera.pos.x, Camera.pos.y, Camera.pos.z, &Camera.pos.roomNumber);
|
||||
LookAt(&Camera, 0);
|
||||
|
||||
|
@ -1079,6 +1087,8 @@ void LookCamera(ITEM_INFO* item)
|
|||
Camera.pos.roomNumber = LaraItem->roomNumber;
|
||||
}
|
||||
|
||||
ItemsCollideCamera();
|
||||
|
||||
GetFloor(Camera.pos.x, Camera.pos.y, Camera.pos.z, &Camera.pos.roomNumber);
|
||||
LookAt(&Camera, 0);
|
||||
|
||||
|
@ -1780,6 +1790,222 @@ void ResetLook()
|
|||
}
|
||||
}
|
||||
|
||||
bool TestBoundsCollideCamera(BOUNDING_BOX* bounds, PHD_3DPOS* pos, short radius)
|
||||
{
|
||||
auto dxBox = TO_DX_BBOX(*pos, bounds);
|
||||
auto sphere = BoundingSphere(Vector3(Camera.pos.x, Camera.pos.y, Camera.pos.z), radius);
|
||||
return sphere.Intersects(dxBox);
|
||||
}
|
||||
|
||||
void ItemPushCamera(BOUNDING_BOX* bounds, PHD_3DPOS* pos, short radius)
|
||||
{
|
||||
auto dx = Camera.pos.x - pos->xPos;
|
||||
auto dz = Camera.pos.z - pos->zPos;
|
||||
auto sin = phd_sin(pos->yRot);
|
||||
auto cos = phd_cos(pos->yRot);
|
||||
auto x = dx * cos - dz * sin;
|
||||
auto z = dx * sin + dz * cos;
|
||||
|
||||
auto xmin = bounds->X1 - radius;
|
||||
auto xmax = bounds->X2 + radius;
|
||||
auto zmin = bounds->Z1 - radius;
|
||||
auto zmax = bounds->Z2 + radius;
|
||||
|
||||
if (x <= xmin || x >= xmax || z <= zmin || z >= zmax)
|
||||
return;
|
||||
|
||||
auto left = x - xmin;
|
||||
auto right = xmax - x;
|
||||
auto top = zmax - z;
|
||||
auto bottom = z - zmin;
|
||||
|
||||
if (left <= right && left <= top && left <= bottom) // Left is closest
|
||||
x -= left;
|
||||
else if (right <= left && right <= top && right <= bottom) // Right is closest
|
||||
x += right;
|
||||
else if (top <= left && top <= right && top <= bottom) // Top is closest
|
||||
z += top;
|
||||
else
|
||||
z -= bottom; // Bottom
|
||||
|
||||
Camera.pos.x = pos->xPos + (cos * x + sin * z);
|
||||
Camera.pos.z = pos->zPos + (cos * z - sin * x);
|
||||
|
||||
auto coll = GetCollisionResult(Camera.pos.x, Camera.pos.y, Camera.pos.z, Camera.pos.roomNumber);
|
||||
if (coll.Position.Floor == NO_HEIGHT || Camera.pos.y > coll.Position.Floor || Camera.pos.y < coll.Position.Ceiling)
|
||||
{
|
||||
Camera.pos.x = CamOldPos.x;
|
||||
Camera.pos.y = CamOldPos.y;
|
||||
Camera.pos.z = CamOldPos.z;
|
||||
Camera.pos.roomNumber = coll.RoomNumber;
|
||||
}
|
||||
}
|
||||
|
||||
static bool CheckItemCollideCamera(ITEM_INFO* item)
|
||||
{
|
||||
auto dx = Camera.pos.x - item->pos.xPos;
|
||||
auto dy = Camera.pos.y - item->pos.yPos;
|
||||
auto dz = Camera.pos.z - item->pos.zPos;
|
||||
|
||||
bool close_enough = dx > -COLL_CHECK_THRESHOLD && dx < COLL_CHECK_THRESHOLD &&
|
||||
dz > -COLL_CHECK_THRESHOLD && dz < COLL_CHECK_THRESHOLD &&
|
||||
dy > -COLL_CHECK_THRESHOLD && dy < COLL_CHECK_THRESHOLD;
|
||||
|
||||
if (!close_enough || !item->collidable || !Objects[item->objectNumber].usingDrawAnimatingItem)
|
||||
return false;
|
||||
|
||||
// TODO: Find a better way to define objects which are collidable with camera.
|
||||
auto obj = &Objects[item->objectNumber];
|
||||
if (obj->intelligent || obj->isPickup || obj->isPuzzleHole || obj->collision == nullptr)
|
||||
return false;
|
||||
|
||||
// Check extents, if any 2 bounds are smaller than threshold, discard.
|
||||
Vector3 extents = TO_DX_BBOX(item->pos, GetBoundsAccurate(item)).Extents;
|
||||
if ((abs(extents.x) < COLL_DISCARD_THRESHOLD && abs(extents.y) < COLL_DISCARD_THRESHOLD) ||
|
||||
(abs(extents.x) < COLL_DISCARD_THRESHOLD && abs(extents.z) < COLL_DISCARD_THRESHOLD) ||
|
||||
(abs(extents.y) < COLL_DISCARD_THRESHOLD && abs(extents.z) < COLL_DISCARD_THRESHOLD))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<short> FillCollideableItemList()
|
||||
{
|
||||
std::vector<short> itemList;
|
||||
auto roomList = CollectConnectedRooms(Camera.pos.roomNumber);
|
||||
|
||||
for (short i = 0; i < g_Level.NumItems; i++)
|
||||
{
|
||||
auto item = &g_Level.Items[i];
|
||||
|
||||
if (!roomList.count(item->roomNumber))
|
||||
continue;
|
||||
|
||||
if (!CheckItemCollideCamera(&g_Level.Items[i]))
|
||||
continue;
|
||||
|
||||
itemList.push_back(i);
|
||||
}
|
||||
|
||||
return itemList;
|
||||
}
|
||||
|
||||
static bool CheckStaticCollideCamera(MESH_INFO* mesh)
|
||||
{
|
||||
auto dx = Camera.pos.x - mesh->pos.xPos;
|
||||
auto dy = Camera.pos.y - mesh->pos.yPos;
|
||||
auto dz = Camera.pos.z - mesh->pos.zPos;
|
||||
|
||||
bool close_enough = dx > -COLL_CHECK_THRESHOLD && dx < COLL_CHECK_THRESHOLD &&
|
||||
dz > -COLL_CHECK_THRESHOLD && dz < COLL_CHECK_THRESHOLD &&
|
||||
dy > -COLL_CHECK_THRESHOLD && dy < COLL_CHECK_THRESHOLD;
|
||||
|
||||
if (!close_enough)
|
||||
return false;
|
||||
|
||||
if (!(mesh->flags & StaticMeshFlags::SM_VISIBLE))
|
||||
return false;
|
||||
|
||||
auto stat = &StaticObjects[mesh->staticNumber];
|
||||
auto extents = Vector3(abs(stat->collisionBox.X1 - stat->collisionBox.X2),
|
||||
abs(stat->collisionBox.Y1 - stat->collisionBox.Y2),
|
||||
abs(stat->collisionBox.Z1 - stat->collisionBox.Z2));
|
||||
|
||||
// Check extents, if any 2 bounds are smaller than threshold, discard.
|
||||
if ((abs(extents.x) < COLL_DISCARD_THRESHOLD && abs(extents.y) < COLL_DISCARD_THRESHOLD) ||
|
||||
(abs(extents.x) < COLL_DISCARD_THRESHOLD && abs(extents.z) < COLL_DISCARD_THRESHOLD) ||
|
||||
(abs(extents.y) < COLL_DISCARD_THRESHOLD && abs(extents.z) < COLL_DISCARD_THRESHOLD))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<MESH_INFO*> FillCollideableStaticsList()
|
||||
{
|
||||
std::vector<MESH_INFO*> staticList;
|
||||
auto roomList = CollectConnectedRooms(Camera.pos.roomNumber);
|
||||
|
||||
for (auto i : roomList)
|
||||
{
|
||||
auto room = &g_Level.Rooms[i];
|
||||
for (short j = 0; j < room->mesh.size(); j++)
|
||||
{
|
||||
if (!CheckStaticCollideCamera(&room->mesh[j]))
|
||||
continue;
|
||||
|
||||
staticList.push_back(&room->mesh[j]);
|
||||
}
|
||||
}
|
||||
|
||||
return staticList;
|
||||
}
|
||||
|
||||
void ItemsCollideCamera()
|
||||
{
|
||||
auto rad = 128;
|
||||
auto itemList = FillCollideableItemList();
|
||||
|
||||
// Collide with the items list
|
||||
|
||||
for (int i = 0; i < itemList.size(); i++)
|
||||
{
|
||||
auto item = &g_Level.Items[itemList[i]];
|
||||
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
auto dx = abs(LaraItem->pos.xPos - item->pos.xPos);
|
||||
auto dy = abs(LaraItem->pos.yPos - item->pos.yPos);
|
||||
auto dz = abs(LaraItem->pos.zPos - item->pos.zPos);
|
||||
|
||||
// If camera is stuck behind some item, and Lara runs off somewhere
|
||||
if (dx > COLL_CANCEL_THRESHOLD || dz > COLL_CANCEL_THRESHOLD || dy > COLL_CANCEL_THRESHOLD)
|
||||
continue;
|
||||
|
||||
auto bounds = GetBoundsAccurate(item);
|
||||
if (TestBoundsCollideCamera(bounds, &item->pos, CAMERA_RADIUS))
|
||||
ItemPushCamera(bounds, &item->pos, rad);
|
||||
|
||||
#ifdef _DEBUG
|
||||
TEN::Renderer::g_Renderer.addDebugBox(TO_DX_BBOX(item->pos, bounds),
|
||||
Vector4(1.0f, 0.0f, 0.0f, 1.0f), RENDERER_DEBUG_PAGE::DIMENSION_STATS);
|
||||
#endif
|
||||
}
|
||||
|
||||
itemList.clear(); // Done
|
||||
|
||||
// Collide with static meshes
|
||||
|
||||
auto staticList = FillCollideableStaticsList();
|
||||
|
||||
for (int i = 0; i < staticList.size(); i++)
|
||||
{
|
||||
auto mesh = staticList[i];
|
||||
auto stat = &StaticObjects[mesh->staticNumber];
|
||||
|
||||
if (!mesh || !stat)
|
||||
return;
|
||||
|
||||
auto dx = abs(LaraItem->pos.xPos - mesh->pos.xPos);
|
||||
auto dy = abs(LaraItem->pos.yPos - mesh->pos.yPos);
|
||||
auto dz = abs(LaraItem->pos.zPos - mesh->pos.zPos);
|
||||
|
||||
if (dx > COLL_CANCEL_THRESHOLD || dz > COLL_CANCEL_THRESHOLD || dy > COLL_CANCEL_THRESHOLD)
|
||||
continue;
|
||||
|
||||
auto bounds = &stat->collisionBox;
|
||||
if (TestBoundsCollideCamera(bounds, &mesh->pos, CAMERA_RADIUS))
|
||||
ItemPushCamera(bounds, &mesh->pos, rad);
|
||||
|
||||
#ifdef _DEBUG
|
||||
TEN::Renderer::g_Renderer.addDebugBox(TO_DX_BBOX(mesh->pos, bounds),
|
||||
Vector4(1.0f, 0.0f, 0.0f, 1.0f), RENDERER_DEBUG_PAGE::DIMENSION_STATS);
|
||||
#endif
|
||||
}
|
||||
|
||||
staticList.clear(); // Done
|
||||
}
|
||||
|
||||
void RumbleScreen()
|
||||
{
|
||||
if (!(GlobalCounter & 0x1FF))
|
||||
|
|
|
@ -81,3 +81,6 @@ void LookLeftRight();
|
|||
void LookUpDown();
|
||||
void ResetLook();
|
||||
void RumbleScreen();
|
||||
bool TestBoundsCollideCamera(BOUNDING_BOX* bounds, PHD_3DPOS* pos, short radius);
|
||||
void ItemPushCamera(BOUNDING_BOX* bounds, PHD_3DPOS* pos, short radius);
|
||||
void ItemsCollideCamera();
|
||||
|
|
|
@ -127,8 +127,7 @@ bool GetCollidedObjects(ITEM_INFO* collidingItem, int radius, bool onlyVisible,
|
|||
dy >= -2048 && dy <= 2048 &&
|
||||
dz >= -2048 && dz <= 2048 &&
|
||||
collidingItem->pos.yPos + radius + 128 >= item->pos.yPos + framePtr->boundingBox.Y1 &&
|
||||
collidingItem->pos.yPos - radius - 128 <= item->pos.yPos + framePtr->boundingBox.Y2 &&
|
||||
collidingItem->floor >= item->pos.yPos)
|
||||
collidingItem->pos.yPos - radius - 128 <= item->pos.yPos + framePtr->boundingBox.Y2)
|
||||
{
|
||||
float s = phd_sin(item->pos.yRot);
|
||||
float c = phd_cos(item->pos.yRot);
|
||||
|
@ -167,29 +166,6 @@ bool GetCollidedObjects(ITEM_INFO* collidingItem, int radius, bool onlyVisible,
|
|||
return (numItems || numMeshes);
|
||||
}
|
||||
|
||||
std::set<int> CollectConnectedRooms(int roomNumber)
|
||||
{
|
||||
std::set<int> result;
|
||||
|
||||
if (g_Level.Rooms.size() <= roomNumber)
|
||||
return result;
|
||||
|
||||
result.insert(roomNumber);
|
||||
|
||||
auto room = &g_Level.Rooms[roomNumber];
|
||||
for (int i = 0; i < room->doors.size(); i++)
|
||||
result.insert(room->doors[i].room);
|
||||
|
||||
for (auto i : result)
|
||||
{
|
||||
room = &g_Level.Rooms[i];
|
||||
for (int j = 0; j < room->doors.size(); j++)
|
||||
result.insert(room->doors[j].room);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void CollideSolidStatics(ITEM_INFO* item, COLL_INFO* coll)
|
||||
{
|
||||
coll->HitTallObject = false;
|
||||
|
|
|
@ -173,5 +173,4 @@ int GetQuadrant(short angle);
|
|||
void CalcItemToFloorRotation(ITEM_INFO* item, int radiusDivide = 1);
|
||||
short GetNearestLedgeAngle(ITEM_INFO* item, COLL_INFO* coll, float& dist);
|
||||
bool CollideSolidBounds(ITEM_INFO* item, BOUNDING_BOX box, PHD_3DPOS pos, COLL_INFO* coll);
|
||||
void CollideSolidStatics(ITEM_INFO* item, COLL_INFO* coll);
|
||||
std::set<int> CollectConnectedRooms(int roomNumber);
|
||||
void CollideSolidStatics(ITEM_INFO* item, COLL_INFO* coll);
|
|
@ -45,8 +45,8 @@ void DropBaddyPickups(ITEM_INFO* item)
|
|||
for (short pickupNumber = item->carriedItem; pickupNumber != NO_ITEM; pickupNumber = pickup->carriedItem)
|
||||
{
|
||||
pickup = &g_Level.Items[pickupNumber];
|
||||
pickup->pos.xPos = (item->pos.xPos & -CLICK(2)) | CLICK(2);
|
||||
pickup->pos.zPos = (item->pos.zPos & -CLICK(2)) | CLICK(2);
|
||||
pickup->pos.xPos = (item->pos.xPos & -CLICK(1)) | CLICK(1);
|
||||
pickup->pos.zPos = (item->pos.zPos & -CLICK(1)) | CLICK(1);
|
||||
|
||||
roomNumber = item->roomNumber;
|
||||
floor = GetFloor(pickup->pos.xPos, item->pos.yPos, pickup->pos.zPos, &roomNumber);
|
||||
|
|
|
@ -186,3 +186,25 @@ PHD_3DPOS GetRoomCenter(int roomNumber)
|
|||
return center;
|
||||
}
|
||||
|
||||
std::set<int> CollectConnectedRooms(int roomNumber)
|
||||
{
|
||||
std::set<int> result;
|
||||
|
||||
if (g_Level.Rooms.size() <= roomNumber)
|
||||
return result;
|
||||
|
||||
result.insert(roomNumber);
|
||||
|
||||
auto room = &g_Level.Rooms[roomNumber];
|
||||
for (int i = 0; i < room->doors.size(); i++)
|
||||
result.insert(room->doors[i].room);
|
||||
|
||||
for (auto i : result)
|
||||
{
|
||||
room = &g_Level.Rooms[i];
|
||||
for (int j = 0; j < room->doors.size(); j++)
|
||||
result.insert(room->doors[j].room);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
|
@ -136,5 +136,6 @@ int IsObjectInRoom(short roomNumber, short objectNumber);
|
|||
bool IsPointInRoom(PHD_3DPOS const & pos, int roomNumber);
|
||||
PHD_3DPOS GetRoomCenter(int roomNumber);
|
||||
int IsRoomOutside(int x, int y, int z);
|
||||
std::set<int> CollectConnectedRooms(int roomNumber);
|
||||
|
||||
FLOOR_INFO* GetSector(ROOM_INFO* r, int x, int z);
|
|
@ -7,6 +7,7 @@
|
|||
#include "animation.h"
|
||||
#include "lara.h"
|
||||
#include "lara_collide.h"
|
||||
#include "collide.h"
|
||||
#include "Sound\sound.h"
|
||||
#include "sphere.h"
|
||||
#include "traps.h"
|
||||
|
@ -15,7 +16,7 @@
|
|||
|
||||
using namespace TEN::Effects::Lara;
|
||||
|
||||
void TriggerElectricityWiresSparks(int x, int z, byte objNum, byte node, int flags)
|
||||
void TriggerElectricityWireSparks(int x, int z, byte objNum, byte node, bool glow)
|
||||
{
|
||||
SPARKS* spark = &Sparks[GetFreeSpark()];
|
||||
spark->on = true;
|
||||
|
@ -26,7 +27,7 @@ void TriggerElectricityWiresSparks(int x, int z, byte objNum, byte node, int fla
|
|||
spark->dG = (GetRandomControl() & 0x7F) + 64;
|
||||
spark->dB = 255;
|
||||
|
||||
if (flags)
|
||||
if (glow)
|
||||
{
|
||||
spark->colFadeSpeed = 1;
|
||||
spark->fadeToBlack = 0;
|
||||
|
@ -36,7 +37,7 @@ void TriggerElectricityWiresSparks(int x, int z, byte objNum, byte node, int fla
|
|||
{
|
||||
spark->colFadeSpeed = 3;
|
||||
spark->fadeToBlack = 4;
|
||||
spark->life = spark->sLife = 16;
|
||||
spark->life = spark->sLife = 24;
|
||||
}
|
||||
|
||||
spark->fxObj = objNum;
|
||||
|
@ -47,7 +48,7 @@ void TriggerElectricityWiresSparks(int x, int z, byte objNum, byte node, int fla
|
|||
spark->z = z;
|
||||
spark->y = 0;
|
||||
|
||||
if (flags)
|
||||
if (glow)
|
||||
{
|
||||
spark->xVel = 0;
|
||||
spark->yVel = 0;
|
||||
|
@ -55,15 +56,16 @@ void TriggerElectricityWiresSparks(int x, int z, byte objNum, byte node, int fla
|
|||
}
|
||||
else
|
||||
{
|
||||
spark->xVel = (GetRandomControl() & 0x1FF) - 256;
|
||||
spark->yVel = GetRandomControl() - 64;
|
||||
spark->zVel = (GetRandomControl() & 0x1FF) - 256;
|
||||
spark->xVel = (GetRandomControl() & 0x1F) - 0x0F;
|
||||
spark->yVel = (GetRandomControl() & 0x1F) - 0x0F;
|
||||
spark->zVel = (GetRandomControl() & 0x1F) - 0x0F;
|
||||
spark->y = (GetRandomControl() & 0x3F) - 0x1F;
|
||||
}
|
||||
spark->friction = 51;
|
||||
spark->maxYvel = 0;
|
||||
spark->gravity = 0;
|
||||
|
||||
if (flags)
|
||||
if (glow)
|
||||
{
|
||||
spark->scalar = 1;
|
||||
spark->def = Objects[ID_DEFAULT_SPRITES].meshIndex + 11;
|
||||
|
@ -79,13 +81,13 @@ void TriggerElectricityWiresSparks(int x, int z, byte objNum, byte node, int fla
|
|||
spark->dSize = spark->size / 2;
|
||||
}
|
||||
|
||||
void TriggerLaraElectricitySparks(int flame)
|
||||
void TriggerElectricitySparks(ITEM_INFO* item, int joint, int flame)
|
||||
{
|
||||
PHD_VECTOR pos;
|
||||
pos.x = 0;
|
||||
pos.y = 0;
|
||||
pos.z = 0;
|
||||
GetLaraJointPosition(&pos, GetRandomControl() % 15);
|
||||
GetJointAbsPosition(item, &pos, joint);
|
||||
|
||||
SPARKS* spark = &Sparks[GetFreeSpark()];
|
||||
|
||||
|
@ -131,159 +133,132 @@ static bool ElectricityWireCheckDeadlyBounds(PHD_VECTOR* pos, short delta)
|
|||
|
||||
void ElectricityWiresControl(short itemNumber)
|
||||
{
|
||||
bool flag = false;
|
||||
int counter = 3;
|
||||
|
||||
ITEM_INFO* item = &g_Level.Items[itemNumber];
|
||||
|
||||
if (item->itemFlags[0] > 2)
|
||||
{
|
||||
TriggerDynamicLight(
|
||||
LaraItem->pos.xPos,
|
||||
LaraItem->pos.yPos,
|
||||
LaraItem->pos.zPos,
|
||||
item->itemFlags[0],
|
||||
0,
|
||||
(GetRandomControl() & 0x1F) + 8 * item->itemFlags[0],
|
||||
(GetRandomControl() & 0x1F) + 8 * item->itemFlags[0]);
|
||||
|
||||
item->itemFlags[0] -= 2;
|
||||
}
|
||||
|
||||
if (TriggerActive(item))
|
||||
{
|
||||
SoundEffect(SFX_TR5_ELECTRIC_WIRES, &item->pos, 0);
|
||||
|
||||
counter = (abs(LaraItem->pos.xPos - item->pos.xPos) > 2048)
|
||||
+ (abs(LaraItem->pos.zPos - item->pos.zPos) > 2048)
|
||||
+ (abs(LaraItem->pos.yPos - item->pos.yPos) > 4096);
|
||||
|
||||
int x = (GetRandomControl() & 0x1F) - 16;
|
||||
int z = (GetRandomControl() & 0x1F) - 16;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (GetRandomControl() & 1)
|
||||
TriggerElectricityWiresSparks(x, z, itemNumber, i + 2, 0);
|
||||
}
|
||||
|
||||
if (!(GlobalCounter & 3))
|
||||
{
|
||||
TriggerElectricityWiresSparks(0, 0, itemNumber, 2, 1);
|
||||
TriggerElectricityWiresSparks(0, 0, itemNumber, 3, 1);
|
||||
TriggerElectricityWiresSparks(0, 0, itemNumber, 4, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
flag = true;
|
||||
}
|
||||
auto item = &g_Level.Items[itemNumber];
|
||||
|
||||
AnimateItem(item);
|
||||
|
||||
if (!Lara.burn && !flag && !counter)
|
||||
if (!TriggerActive(item))
|
||||
return;
|
||||
|
||||
SoundEffect(SFX_TR5_ELECTRIC_WIRES, &item->pos, 0);
|
||||
|
||||
GetCollidedObjects(item, SECTOR(4), true, CollidedItems, nullptr, 0) && CollidedItems[0];
|
||||
|
||||
auto obj = &Objects[item->objectNumber];
|
||||
|
||||
auto cableBox = TO_DX_BBOX(item->pos, GetBoundsAccurate(item));
|
||||
auto cableBottomPlane = cableBox.Center.y + cableBox.Extents.y - CLICK(1);
|
||||
|
||||
int currentEndNode = 0;
|
||||
int flashingNode = GlobalCounter % 3;
|
||||
|
||||
for (int i = 0; i < obj->nmeshes; i++)
|
||||
{
|
||||
GetLaraDeadlyBounds();
|
||||
|
||||
for (int i = 2; i < 28; i += 3)
|
||||
{
|
||||
PHD_VECTOR pos;
|
||||
pos.x = 0;
|
||||
pos.y = 0;
|
||||
pos.z = 0;
|
||||
|
||||
GetJointAbsPosition(item, &pos, i);
|
||||
|
||||
if (ElectricityWireCheckDeadlyBounds(&pos, item->triggerFlags))
|
||||
{
|
||||
for (int i = 0; i < 48; i++)
|
||||
TriggerLaraElectricitySparks(0);
|
||||
|
||||
item->itemFlags[0] = 28;
|
||||
LaraBurn(LaraItem);
|
||||
Lara.burnBlue = 1;
|
||||
Lara.burnCount = 48;
|
||||
LaraItem->hitPoints = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int i = 8;
|
||||
int j = 0;
|
||||
counter = GlobalCounter % 3;
|
||||
short roomNumber = item->roomNumber;
|
||||
bool water = false;
|
||||
|
||||
for (int i = 8; i < 27; i += 9, j++)
|
||||
{
|
||||
PHD_VECTOR pos;
|
||||
pos.x = 0;
|
||||
pos.y = 0;
|
||||
pos.z = 256;
|
||||
auto pos = PHD_VECTOR(0, 0, CLICK(1));
|
||||
GetJointAbsPosition(item, &pos, i);
|
||||
|
||||
if (GetRandomControl() & 1 && !flag)
|
||||
{
|
||||
TriggerDynamicLight(pos.x, pos.y, pos.z, 12, 0, ((GetRandomControl() & 0x3F) + 128) / 2, (GetRandomControl() & 0x3F) + 128);
|
||||
}
|
||||
if (pos.y < cableBottomPlane)
|
||||
continue;
|
||||
|
||||
roomNumber = item->roomNumber;
|
||||
GetFloor(pos.x, pos.y, pos.z, &roomNumber);
|
||||
ROOM_INFO* r = &g_Level.Rooms[roomNumber];
|
||||
if (((GetRandomControl() & 0x0F) < 8) && flashingNode == currentEndNode)
|
||||
TriggerDynamicLight(pos.x, pos.y, pos.z, 10, 0, ((GetRandomControl() & 0x3F) + 96) / 2, (GetRandomControl() & 0x3F) + 128);
|
||||
|
||||
if (r->flags & ENV_FLAG_WATER)
|
||||
for (int s = 0; s < 3; s++)
|
||||
{
|
||||
if (counter == j)
|
||||
if (GetRandomControl() & 1)
|
||||
{
|
||||
SetupRipple(pos.x, r->maxceiling, pos.z, (GetRandomControl() & 7) + 32, 16, Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_RIPPLES);
|
||||
int x = (GetRandomControl() & 0x3F) - 0x1F;
|
||||
int z = (GetRandomControl() & 0x3F) - 0x1F;
|
||||
TriggerElectricityWireSparks(x, z, itemNumber, s + 2, false);
|
||||
TriggerElectricityWireSparks(x, z, itemNumber, s + 2, true);
|
||||
}
|
||||
|
||||
water = true;
|
||||
}
|
||||
|
||||
currentEndNode++;
|
||||
}
|
||||
|
||||
if (!flag && !Lara.burn)
|
||||
if (GetRandomControl() & 1)
|
||||
return;
|
||||
|
||||
int k = 0;
|
||||
while (CollidedItems[k] != nullptr)
|
||||
{
|
||||
if (water)
|
||||
auto collItem = CollidedItems[k];
|
||||
auto collObj = &Objects[collItem->objectNumber];
|
||||
|
||||
k++;
|
||||
|
||||
if (collItem->objectNumber != ID_LARA && !collObj->intelligent)
|
||||
continue;
|
||||
|
||||
bool isWaterNearby = false;
|
||||
auto npcBox = TO_DX_BBOX(collItem->pos, GetBoundsAccurate(collItem));
|
||||
|
||||
for (int i = 0; i < obj->nmeshes; i++)
|
||||
{
|
||||
int flipNumber = g_Level.Rooms[roomNumber].flipNumber;
|
||||
auto pos = PHD_VECTOR(0, 0, CLICK(1));
|
||||
GetJointAbsPosition(item, &pos, i);
|
||||
|
||||
PHD_VECTOR pos1;
|
||||
pos1.x = 0;
|
||||
pos1.y = 0;
|
||||
pos1.z = 0;
|
||||
GetLaraJointPosition(&pos1, LM_LFOOT);
|
||||
short roomNumber = item->roomNumber;
|
||||
auto floor = GetFloor(pos.x, pos.y, pos.z, &roomNumber);
|
||||
|
||||
short roomNumber1 = LaraItem->roomNumber;
|
||||
GetFloor(pos1.x, pos1.y, pos1.z, &roomNumber1);
|
||||
|
||||
PHD_VECTOR pos2;
|
||||
pos2.x = 0;
|
||||
pos2.y = 0;
|
||||
pos2.z = 0;
|
||||
GetLaraJointPosition(&pos2, LM_RFOOT);
|
||||
|
||||
short roomNumber2 = LaraItem->roomNumber;
|
||||
GetFloor(pos2.x, pos2.y, pos2.z, &roomNumber2);
|
||||
|
||||
if (g_Level.Rooms[roomNumber1].flipNumber == flipNumber || g_Level.Rooms[roomNumber2].flipNumber == flipNumber)
|
||||
bool waterTouch = false;
|
||||
if (g_Level.Rooms[roomNumber].flags & ENV_FLAG_WATER)
|
||||
{
|
||||
if (LaraItem->hitPoints > 32)
|
||||
waterTouch = true;
|
||||
if ((GetRandomControl() & 127) < 16)
|
||||
SetupRipple(pos.x, floor->FloorHeight(pos.x, pos.y, pos.z), pos.z, (GetRandomControl() & 7) + 32, 16, Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_RIPPLES);
|
||||
}
|
||||
|
||||
if (pos.y < cableBottomPlane)
|
||||
continue;
|
||||
|
||||
for (int j = 0; j < collObj->nmeshes; j++)
|
||||
{
|
||||
PHD_VECTOR collPos = {};
|
||||
GetJointAbsPosition(collItem, &collPos, j);
|
||||
|
||||
auto collJointRoom = GetCollisionResult(collPos.x, collPos.y, collPos.z, collItem->roomNumber).RoomNumber;
|
||||
|
||||
if (!isWaterNearby && waterTouch && roomNumber == collJointRoom)
|
||||
isWaterNearby = true;
|
||||
}
|
||||
|
||||
bool instantKill = BoundingSphere(Vector3(pos.x, pos.y, pos.z), CLICK(0.25f)).Intersects(npcBox);
|
||||
|
||||
if (isWaterNearby || instantKill)
|
||||
{
|
||||
if (collItem->data.is<LaraInfo*>())
|
||||
{
|
||||
SoundEffect(SFX_TR4_LARA_ELECTRIC_CRACKLES, &LaraItem->pos, 0);
|
||||
TriggerLaraElectricitySparks(0);
|
||||
TriggerLaraElectricitySparks(1);
|
||||
TriggerDynamicLight(pos1.x, pos1.y, pos1.z, 8, 0, GetRandomControl() & 0x7F, (GetRandomControl() & 0x3F) + 128);
|
||||
LaraItem->hitPoints -= 10;
|
||||
auto lara = (LaraInfo*&)collItem->data;
|
||||
lara->burnBlue = 1;
|
||||
lara->burnCount = 48;
|
||||
|
||||
if (!isWaterNearby)
|
||||
LaraBurn(collItem);
|
||||
}
|
||||
|
||||
if (instantKill)
|
||||
collItem->hitPoints = 0;
|
||||
else
|
||||
collItem->hitPoints -= 8;
|
||||
|
||||
for (int j = 0; j < collObj->nmeshes; j++)
|
||||
{
|
||||
item->itemFlags[0] = 28;
|
||||
LaraBurn(LaraItem);
|
||||
Lara.burnBlue = 1;
|
||||
Lara.burnCount = 48;
|
||||
LaraItem->hitPoints = 0;
|
||||
if ((GetRandomControl() & 127) < 16)
|
||||
TriggerElectricitySparks(collItem, j, false);
|
||||
}
|
||||
|
||||
TriggerDynamicLight(
|
||||
collItem->pos.xPos,
|
||||
collItem->pos.yPos,
|
||||
collItem->pos.zPos,
|
||||
5,
|
||||
0,
|
||||
(GetRandomControl() & 0x3F) + 0x2F,
|
||||
(GetRandomControl() & 0x3F) + 0x4F);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
void TriggerElectricityWiresSparks(int x, int z, byte objNum, byte node, int flags);
|
||||
void TriggerLaraElectricitySparks(int flame);
|
||||
void ElectricityWiresControl(short itemNumber);
|
File diff suppressed because it is too large
Load diff
|
@ -2,7 +2,7 @@
|
|||
#include "items.h"
|
||||
#include "collide.h"
|
||||
|
||||
enum class BoatGetOn
|
||||
enum class BoatMountType
|
||||
{
|
||||
None = 0,
|
||||
WaterRight = 1,
|
||||
|
@ -12,18 +12,20 @@ enum class BoatGetOn
|
|||
};
|
||||
|
||||
void InitialiseSpeedBoat(short itemNum);
|
||||
void SpeedBoatCollision(short itemNum, ITEM_INFO* litem, COLL_INFO* coll);
|
||||
void SpeedBoatControl(short itemNumber);
|
||||
void DoBoatWakeEffect(ITEM_INFO* boat);
|
||||
void SpeedBoatGetOff(ITEM_INFO* boat);
|
||||
bool SpeedBoatCanGetOff(int direction);
|
||||
BoatGetOn SpeedBoatCheckGeton(short itemNum, COLL_INFO* coll);
|
||||
int SpeedBoatTestWaterHeight(ITEM_INFO* item, int zOff, int xOff, PHD_VECTOR* pos);
|
||||
void SpeedBoatDoBoatShift(int itemNum);
|
||||
void DoBoatWakeEffect(ITEM_INFO* sBoatItem);
|
||||
BoatMountType GetSpeedBoatMountType(ITEM_INFO* laraItem, ITEM_INFO* sBoatItem, COLL_INFO* coll);
|
||||
bool TestSpeedBoatDismount(ITEM_INFO* sBoatItem, int direction);
|
||||
void DoSpeedBoatDismount(ITEM_INFO* laraItem, ITEM_INFO* sBoatItem);
|
||||
int SpeedBoatTestWaterHeight(ITEM_INFO* sBoatItem, int zOff, int xOff, PHD_VECTOR* pos);
|
||||
|
||||
void SpeedBoatDoBoatShift(ITEM_INFO* sBoatItem, int itemNum);
|
||||
short SpeedBoatDoShift(ITEM_INFO* skidoo, PHD_VECTOR* pos, PHD_VECTOR* old);
|
||||
|
||||
int GetSpeedBoatHitAnim(ITEM_INFO* sBoatItem, PHD_VECTOR* moved);
|
||||
int SpeedBoatDoBoatDynamics(int height, int fallspeed, int* y);
|
||||
int SpeedBoatDynamics(short itemNum);
|
||||
bool SpeedBoatUserControl(ITEM_INFO* boat);
|
||||
void SpeedBoatAnimation(ITEM_INFO* boat, int collide);
|
||||
int SpeedBoatDynamics(ITEM_INFO* laraItem, short itemNum);
|
||||
bool SpeedBoatUserControl(ITEM_INFO* sBoatItem);
|
||||
void SpeedBoatAnimation(ITEM_INFO* laraItem, ITEM_INFO* sBoatItem, int collide);
|
||||
void SpeedBoatSplash(ITEM_INFO* item, long fallspeed, long water);
|
||||
short SpeedBoatDoShif(ITEM_INFO* skidoo, PHD_VECTOR* pos, PHD_VECTOR* old);
|
||||
int SpeedBoatGetCollisionAnim(ITEM_INFO* skidoo, PHD_VECTOR* moved);
|
||||
void SpeedBoatCollision(short itemNum, ITEM_INFO* laraItem, COLL_INFO* coll);
|
||||
void SpeedBoatControl(short itemNum);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
struct BOAT_INFO {
|
||||
|
||||
struct BOAT_INFO
|
||||
{
|
||||
int boatTurn;
|
||||
int leftFallspeed;
|
||||
int rightFallspeed;
|
||||
|
@ -8,4 +10,4 @@ struct BOAT_INFO {
|
|||
short tiltAngle;
|
||||
short extraRotation;
|
||||
short propRot;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include "animation.h"
|
||||
#include "items.h"
|
||||
|
||||
constexpr auto MAX_ROLLINGBALL_SPEED = WALL_SIZE * 3;
|
||||
|
||||
void RollingBallCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
|
||||
{
|
||||
ITEM_INFO* item = &g_Level.Items[itemNumber];
|
||||
|
@ -47,10 +49,7 @@ void RollingBallControl(short itemNumber)
|
|||
item->pos.yPos += item->fallspeed;
|
||||
item->pos.zPos += item->itemFlags[1] / 32;
|
||||
|
||||
short roomNumber = item->roomNumber;
|
||||
FLOOR_INFO* floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
|
||||
int height = GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos);
|
||||
int dh = height - 512;
|
||||
int dh = GetCollisionResult(item).Position.Floor - CLICK(2);
|
||||
|
||||
if (item->pos.yPos > dh)
|
||||
{
|
||||
|
@ -81,69 +80,77 @@ void RollingBallControl(short itemNumber)
|
|||
}
|
||||
}
|
||||
|
||||
int x = item->pos.xPos;
|
||||
int y = item->pos.yPos;
|
||||
int z = item->pos.zPos;
|
||||
|
||||
int frontX = item->pos.xPos;
|
||||
int frontZ = item->pos.zPos + 128;
|
||||
int backX = item->pos.xPos;
|
||||
int backZ = item->pos.zPos - 128;
|
||||
int rightX = item->pos.xPos + 128;
|
||||
int frontZ = item->pos.zPos + CLICK(0.5f);
|
||||
int backX = item->pos.xPos;
|
||||
int backZ = item->pos.zPos - CLICK(0.5f);
|
||||
int rightX = item->pos.xPos + CLICK(0.5f);
|
||||
int rightZ = item->pos.zPos;
|
||||
int leftX = item->pos.xPos - 128;
|
||||
int leftZ = item->pos.zPos;
|
||||
int leftX = item->pos.xPos - CLICK(0.5f);
|
||||
int leftZ = item->pos.zPos;
|
||||
|
||||
floor = GetFloor(frontX, item->pos.yPos, frontZ, &roomNumber);
|
||||
int frontHeight = GetFloorHeight(floor, frontX, item->pos.yPos, frontZ) - 512;
|
||||
floor = GetFloor(backX, item->pos.yPos, backZ, &roomNumber);
|
||||
int backHeight = GetFloorHeight(floor, backX, item->pos.yPos, backZ) - 512;
|
||||
floor = GetFloor(rightX, item->pos.yPos, rightZ, &roomNumber);
|
||||
int rightHeight = GetFloorHeight(floor, rightX, item->pos.yPos, rightZ) - 512;
|
||||
floor = GetFloor(leftX, item->pos.yPos, leftZ, &roomNumber);
|
||||
int leftHeight = GetFloorHeight(floor, leftX, item->pos.yPos, leftZ) - 512;
|
||||
auto frontFloor = GetCollisionResult(frontX, item->pos.yPos, frontZ, item->roomNumber);
|
||||
auto backFloor = GetCollisionResult(backX, item->pos.yPos, backZ, item->roomNumber);
|
||||
auto rightFloor = GetCollisionResult(rightX, item->pos.yPos, rightZ, item->roomNumber);
|
||||
auto leftFloor = GetCollisionResult(leftX, item->pos.yPos, leftZ, item->roomNumber);
|
||||
|
||||
int frontHeight = frontFloor.Position.Floor - CLICK(2);
|
||||
int backHeight = backFloor.Position.Floor - CLICK(2);
|
||||
int rightHeight = rightFloor.Position.Floor - CLICK(2);
|
||||
int leftHeight = leftFloor.Position.Floor - CLICK(2);
|
||||
|
||||
int frontCeiling = frontFloor.Position.Ceiling + CLICK(2);
|
||||
int backCeiling = backFloor.Position.Ceiling + CLICK(2);
|
||||
int rightCeiling = rightFloor.Position.Ceiling + CLICK(2);
|
||||
int leftCeiling = leftFloor.Position.Ceiling + CLICK(2);
|
||||
|
||||
frontX = item->pos.xPos;
|
||||
frontZ = item->pos.zPos + 512;
|
||||
backX = item->pos.xPos;
|
||||
backZ = item->pos.zPos - 512;
|
||||
rightX = item->pos.xPos + 512;
|
||||
frontZ = item->pos.zPos + CLICK(2);
|
||||
backX = item->pos.xPos;
|
||||
backZ = item->pos.zPos - CLICK(2);
|
||||
rightX = item->pos.xPos + CLICK(2);
|
||||
rightZ = item->pos.zPos;
|
||||
leftX = item->pos.xPos - 512;
|
||||
leftZ = item->pos.zPos;
|
||||
leftX = item->pos.xPos - CLICK(2);
|
||||
leftZ = item->pos.zPos;
|
||||
|
||||
floor = GetFloor(frontX, item->pos.yPos, frontZ, &roomNumber);
|
||||
int frontFarHeight = GetFloorHeight(floor, frontX, item->pos.yPos, frontZ) - 512;
|
||||
floor = GetFloor(backX, item->pos.yPos, backZ, &roomNumber);
|
||||
int backFarHeight = GetFloorHeight(floor, backX, item->pos.yPos, backZ) - 512;
|
||||
floor = GetFloor(rightX, item->pos.yPos, rightZ, &roomNumber);
|
||||
int rightFarHeight = GetFloorHeight(floor, rightX, item->pos.yPos, rightZ) - 512;
|
||||
floor = GetFloor(leftX, item->pos.yPos, leftZ, &roomNumber);
|
||||
int leftFarHeight = GetFloorHeight(floor, leftX, item->pos.yPos, leftZ) - 512;
|
||||
auto fronFarFloor = GetCollisionResult(frontX, item->pos.yPos, frontZ, item->roomNumber);
|
||||
auto backFarFloor = GetCollisionResult(backX, item->pos.yPos, backZ, item->roomNumber);
|
||||
auto rightFarFloor = GetCollisionResult(rightX, item->pos.yPos, rightZ, item->roomNumber);
|
||||
auto leftFarFloor = GetCollisionResult(leftX, item->pos.yPos, leftZ, item->roomNumber);
|
||||
|
||||
if (item->pos.yPos - dh > -256 ||
|
||||
item->pos.yPos - frontFarHeight >= 512 ||
|
||||
item->pos.yPos - rightFarHeight >= 512 ||
|
||||
item->pos.yPos - backFarHeight >= 512 ||
|
||||
item->pos.yPos - leftFarHeight >= 512)
|
||||
int frontFarHeight = fronFarFloor.Position.Floor - CLICK(2);
|
||||
int backFarHeight = backFarFloor.Position.Floor - CLICK(2);
|
||||
int rightFarHeight = rightFarFloor.Position.Floor - CLICK(2);
|
||||
int leftFarHeight = leftFarFloor.Position.Floor - CLICK(2);
|
||||
|
||||
int frontFarCeiling = fronFarFloor.Position.Ceiling + CLICK(2);
|
||||
int backFarCeiling = backFarFloor.Position.Ceiling + CLICK(2);
|
||||
int rightFarCeiling = rightFarFloor.Position.Ceiling + CLICK(2);
|
||||
int leftFarCeiling = leftFarFloor.Position.Ceiling + CLICK(2);
|
||||
|
||||
if (item->pos.yPos - dh > -CLICK(1) ||
|
||||
item->pos.yPos - frontFarHeight >= CLICK(2) ||
|
||||
item->pos.yPos - rightFarHeight >= CLICK(2) ||
|
||||
item->pos.yPos - backFarHeight >= CLICK(2) ||
|
||||
item->pos.yPos - leftFarHeight >= CLICK(2))
|
||||
{
|
||||
int counterZ = 0;
|
||||
|
||||
if (frontFarHeight - dh <= 256)
|
||||
if (frontFarHeight - dh <= CLICK(1))
|
||||
{
|
||||
if (frontFarHeight - dh < -1024 || frontHeight - dh < -256)
|
||||
if (frontFarHeight - dh < -CLICK(4) || frontHeight - dh < -CLICK(1))
|
||||
{
|
||||
if (item->itemFlags[1] <= 0)
|
||||
{
|
||||
if (!item->itemFlags[1] && item->itemFlags[0])
|
||||
{
|
||||
item->pos.zPos = (item->pos.zPos & (~1023)) | 512;
|
||||
item->pos.zPos = (item->pos.zPos & ~(CLICK(4) - 1)) | CLICK(2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
item->itemFlags[1] = -item->itemFlags[1] / 2;
|
||||
item->pos.zPos = (item->pos.zPos & (~1023)) | 512;
|
||||
item->pos.zPos = (item->pos.zPos & ~(CLICK(4) - 1)) | CLICK(2);
|
||||
}
|
||||
}
|
||||
else if (frontHeight == dh)
|
||||
|
@ -156,21 +163,21 @@ void RollingBallControl(short itemNumber)
|
|||
}
|
||||
}
|
||||
|
||||
if (backHeight - dh <= 256)
|
||||
if (backHeight - dh <= CLICK(1))
|
||||
{
|
||||
if (backFarHeight - dh < -1024 || backHeight - dh < -256)
|
||||
if (backFarHeight - dh < -CLICK(4) || backHeight - dh < -CLICK(1))
|
||||
{
|
||||
if (item->itemFlags[1] >= 0)
|
||||
{
|
||||
if (!item->itemFlags[1] && item->itemFlags[0])
|
||||
{
|
||||
item->pos.zPos = (item->pos.zPos & (~1023)) | 512;
|
||||
item->pos.zPos = (item->pos.zPos & ~(CLICK(4) - 1)) | CLICK(2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
item->itemFlags[1] = -item->itemFlags[1] / 2;
|
||||
item->pos.zPos = (item->pos.zPos & (~1023)) | 512;
|
||||
item->pos.zPos = (item->pos.zPos & ~(CLICK(4) - 1)) | CLICK(2);
|
||||
}
|
||||
}
|
||||
else if (backHeight == dh)
|
||||
|
@ -193,21 +200,21 @@ void RollingBallControl(short itemNumber)
|
|||
|
||||
int counterX = 0;
|
||||
|
||||
if (leftHeight - dh <= 256)
|
||||
if (leftHeight - dh <= CLICK(1))
|
||||
{
|
||||
if (leftFarHeight - dh < -1024 || leftHeight - dh < -256)
|
||||
if (leftFarHeight - dh < -CLICK(4) || leftHeight - dh < -CLICK(1))
|
||||
{
|
||||
if (item->itemFlags[0] >= 0)
|
||||
{
|
||||
if (!item->itemFlags[0] && item->itemFlags[1])
|
||||
{
|
||||
item->pos.xPos = (item->pos.xPos & (~1023)) | 512;
|
||||
item->pos.xPos = (item->pos.xPos & ~(CLICK(4) - 1)) | CLICK(2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
item->itemFlags[0] = -item->itemFlags[0] / 2;
|
||||
item->pos.xPos = (item->pos.xPos & (~1023)) | 512;
|
||||
item->pos.xPos = (item->pos.xPos & ~(CLICK(4) - 1)) | CLICK(2);
|
||||
}
|
||||
}
|
||||
else if (leftHeight == dh)
|
||||
|
@ -220,21 +227,21 @@ void RollingBallControl(short itemNumber)
|
|||
}
|
||||
}
|
||||
|
||||
if (rightHeight - dh <= 256)
|
||||
if (rightHeight - dh <= CLICK(1))
|
||||
{
|
||||
if (rightFarHeight - dh < -1024 || rightHeight - dh < -256)
|
||||
if (rightFarHeight - dh < -CLICK(4) || rightHeight - dh < -CLICK(1))
|
||||
{
|
||||
if (item->itemFlags[0] <= 0)
|
||||
{
|
||||
if (!item->itemFlags[0] && item->itemFlags[1])
|
||||
{
|
||||
item->pos.xPos = (item->pos.xPos & (~1023)) | 512;
|
||||
item->pos.xPos = (item->pos.xPos & ~(CLICK(4) - 1)) | CLICK(2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
item->itemFlags[0] = -item->itemFlags[0] / 2;
|
||||
item->pos.xPos = (item->pos.xPos & (~1023)) | 512;
|
||||
item->pos.xPos = (item->pos.xPos & ~(CLICK(4) - 1)) | CLICK(2);
|
||||
}
|
||||
}
|
||||
else if (rightHeight == dh)
|
||||
|
@ -256,20 +263,20 @@ void RollingBallControl(short itemNumber)
|
|||
}
|
||||
}
|
||||
|
||||
GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
|
||||
auto roomNumber = GetCollisionResult(item).RoomNumber;
|
||||
|
||||
if (item->roomNumber != roomNumber)
|
||||
ItemNewRoom(itemNumber, roomNumber);
|
||||
|
||||
if (item->itemFlags[0] > 3072)
|
||||
item->itemFlags[0] = 3072;
|
||||
else if (item->itemFlags[0] < -3072)
|
||||
item->itemFlags[0] = -3072;
|
||||
if (item->itemFlags[0] > MAX_ROLLINGBALL_SPEED)
|
||||
item->itemFlags[0] = MAX_ROLLINGBALL_SPEED;
|
||||
else if (item->itemFlags[0] < -MAX_ROLLINGBALL_SPEED)
|
||||
item->itemFlags[0] = -MAX_ROLLINGBALL_SPEED;
|
||||
|
||||
if (item->itemFlags[1] > 3072)
|
||||
item->itemFlags[1] = 3072;
|
||||
else if (item->itemFlags[1] < -3072)
|
||||
item->itemFlags[1] = -3072;
|
||||
if (item->itemFlags[1] > MAX_ROLLINGBALL_SPEED)
|
||||
item->itemFlags[1] = MAX_ROLLINGBALL_SPEED;
|
||||
else if (item->itemFlags[1] < -MAX_ROLLINGBALL_SPEED)
|
||||
item->itemFlags[1] = -MAX_ROLLINGBALL_SPEED;
|
||||
|
||||
short angle = 0;
|
||||
|
||||
|
|
|
@ -285,8 +285,8 @@ enum GAME_OBJECT_ID : short
|
|||
ID_BURNING_ROOTS,
|
||||
ID_ROPE, // TR4 - OK but needs rendering
|
||||
ID_FIREROPE,
|
||||
ID_POLEROPE,
|
||||
ID_ELECTRICAL_CABLES,
|
||||
ID_POLEROPE, // TR4 - OK
|
||||
ID_ELECTRICAL_CABLES, // TR5 - OK
|
||||
ID_BURNING_FLOOR,
|
||||
ID_DARTS, // TR4 - OK but needs rendering
|
||||
ID_DART_EMITTER, // TR4 - OK
|
||||
|
|
|
@ -1247,21 +1247,17 @@ void LoadSprites()
|
|||
|
||||
void GetCarriedItems()
|
||||
{
|
||||
int i;
|
||||
ITEM_INFO* item, *item2;
|
||||
short linknum;
|
||||
|
||||
for (i = 0; i < g_Level.NumItems; ++i)
|
||||
for (int i = 0; i < g_Level.NumItems; ++i)
|
||||
g_Level.Items[i].carriedItem = NO_ITEM;
|
||||
|
||||
for (i = 0; i < g_Level.NumItems; ++i)
|
||||
for (int i = 0; i < g_Level.NumItems; ++i)
|
||||
{
|
||||
item = &g_Level.Items[i];
|
||||
auto item = &g_Level.Items[i];
|
||||
if (Objects[item->objectNumber].intelligent || item->objectNumber >= ID_SEARCH_OBJECT1 && item->objectNumber <= ID_SEARCH_OBJECT3)
|
||||
{
|
||||
for (linknum = g_Level.Rooms[item->roomNumber].itemNumber; linknum != NO_ITEM; linknum = g_Level.Items[linknum].nextItem)
|
||||
for (short linknum = g_Level.Rooms[item->roomNumber].itemNumber; linknum != NO_ITEM; linknum = g_Level.Items[linknum].nextItem)
|
||||
{
|
||||
item2 = &g_Level.Items[linknum];
|
||||
auto item2 = &g_Level.Items[linknum];
|
||||
if (abs(item2->pos.xPos - item->pos.xPos) < 512
|
||||
&& abs(item2->pos.zPos - item->pos.zPos) < 512
|
||||
&& abs(item2->pos.yPos - item->pos.yPos) < 256
|
||||
|
@ -1279,19 +1275,15 @@ void GetCarriedItems()
|
|||
|
||||
void GetAIPickups()
|
||||
{
|
||||
int i, num;
|
||||
ITEM_INFO* item;
|
||||
AI_OBJECT* object;
|
||||
|
||||
for (i = 0; i < g_Level.NumItems; ++i)
|
||||
for (int i = 0; i < g_Level.NumItems; ++i)
|
||||
{
|
||||
item = &g_Level.Items[i];
|
||||
auto item = &g_Level.Items[i];
|
||||
if (Objects[item->objectNumber].intelligent)
|
||||
{
|
||||
item->aiBits = 0;
|
||||
for (num = 0; num < g_Level.AIObjects.size(); ++num)
|
||||
for (int num = 0; num < g_Level.AIObjects.size(); ++num)
|
||||
{
|
||||
object = &g_Level.AIObjects[num];
|
||||
auto object = &g_Level.AIObjects[num];
|
||||
if (abs(object->x - item->pos.xPos) < 512
|
||||
&& abs(object->z - item->pos.zPos) < 512
|
||||
&& object->roomNumber == item->roomNumber
|
||||
|
@ -1303,6 +1295,7 @@ void GetAIPickups()
|
|||
object->roomNumber = NO_ROOM;
|
||||
}
|
||||
}
|
||||
|
||||
item->TOSSPAD |= item->aiBits << 8 | (char) item->itemFlags[3];
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue