Merge branch 'master' into renderer_refactor

This commit is contained in:
MontyTRC89 2021-12-17 05:57:19 +01:00
commit 9c48aa227b
19 changed files with 1292 additions and 1076 deletions

View file

@ -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];
}

View file

@ -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++;
}
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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))

View file

@ -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();

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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;
}

View file

@ -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);

View file

@ -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;
}
}
}

View file

@ -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

View file

@ -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);

View file

@ -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;
};
};

View file

@ -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;

View file

@ -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

View file

@ -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];
}
}