TombEngine/TR5Main/Objects/statue.cpp

403 lines
8.5 KiB
C++
Raw Normal View History

#include "newobjects.h"
#include "../Global/global.h"
#include "../Game/box.h"
#include "../Game/effect2.h"
#include "../Game/items.h"
#include "../Game/lot.h"
#include "../Game/effects.h"
#include "../Game/draw.h"
BITE_INFO swordBite = { 0, 37, 550, 15 };
// for TR2 and TR3 statue (compatible by any statue entity)
// the statue object need to be after the normal one:
// ex: ID_SWORD_GUARDIAN: 256, ID_SWORD_GUARDIAN_STATUE: 257
void __cdecl DrawStatue(ITEM_INFO* item)
{
OBJECT_INFO* obj;
CREATURE_INFO* creature;
int* bones;
int clip, i, poppush, frac, rate, bit;
__int16* frames[2];
__int16* extra_rotation;
__int16* rotation1, *rotation2;
__int16** normal, **statue;
creature = (CREATURE_INFO*)item->data;
frac = GetFrame_D2(item, frames, &rate);
if (item->hitPoints <= 0 && item->status != ITEM_ACTIVE && item->meshBits != 0)
item->meshBits = item->meshBits >> 1;
obj = &Objects[item->objectNumber];
//if (obj->shadowSize)
// S_PrintShadow(obj->shadowSize, frames[0], item, NULL);
phd_PushMatrix();
phd_TranslateAbs(item->pos.xPos, item->pos.yPos, item->pos.zPos);
phd_RotYXZ(item->pos.yRot, item->pos.xRot, item->pos.zRot);
if (phd_ClipBoundingBox(frames[0]))
{
CalculateObjectLighting(item, frames[0]);
extra_rotation = (__int16*)item->data;
// all entity have the statue slot after it, (ex: ID_SWORD_GUARDIAN: 256, ID_SWORD_GUARDIAN_STATUE: 257)
normal = &Meshes[Objects[ID_SAS].meshIndex];
statue = &Meshes[Objects[ID_SWAT].meshIndex];
bones = Bones + obj->boneIndex;
bit = 1;
if (!frac)
{
phd_TranslateRel((int)*(frames[0] + 6), (int)*(frames[0] + 7), (int)*(frames[0] + 8)); // can be [0][6] etc.. ?
rotation1 = (__int16*)(frames[0] + 9);
gar_RotYXZsuperpack(&rotation1, 0);
if (item->meshBits & bit)
phd_PutPolygons(*normal);
else
phd_PutPolygons(*statue);
normal++;
statue++;
for (i = (obj->nmeshes - 1); i > 0; i--, bones += 4, normal++, statue++)
{
poppush = *bones;
if (poppush & 1)
{
phd_PopMatrix();
phd_PopDxMatrix();
}
if (poppush & 2)
phd_PushMatrix();
phd_TranslateRel(*(bones + 1), *(bones + 2), *(bones + 3));
gar_RotYXZsuperpack(&rotation1, 0);
if (extra_rotation && (poppush & (ROT_X|ROT_Y|ROT_Z)))
{
if (poppush & ROT_Y)
phd_RotY(*(extra_rotation++));
if (poppush & ROT_X)
phd_RotX(*(extra_rotation++));
if (poppush & ROT_Z)
phd_RotZ(*(extra_rotation++));
}
bit <<= 1;
if (item->meshBits & bit)
phd_PutPolygons(*normal);
else
phd_PutPolygons(*statue);
}
}
else
{
InitInterpolate(frac, rate);
phd_TranslateRel_ID((int)*(frames[0] + 6), (int)*(frames[0] + 7), (int)*(frames[0] + 8),
(int)*(frames[1] + 6), (int)*(frames[1] + 7), (int)*(frames[1] + 8));
rotation1 = (short*)(frames[0] + 9);
rotation2 = (short*)(frames[1] + 9);
gar_RotYXZsuperpack_I(&rotation1, &rotation2, 0);
if (item->meshBits & bit)
phd_PutPolygons_I(*normal);
else
phd_PutPolygons_I(*statue);
normal++;
statue++;
for (i = (obj->nmeshes - 1); i > 0; i--, bones += 4, normal++, statue++)
{
poppush = *bones;
if (poppush & 1)
phd_PopMatrix_I();
if (poppush & 2)
phd_PushMatrix_I();
phd_TranslateRel_I(*(bones + 1), *(bones + 2), *(bones + 3));
gar_RotYXZsuperpack_I(&rotation1, &rotation2, 0);
if (extra_rotation && (poppush & (ROT_X|ROT_Y|ROT_Z)))
{
if (poppush & ROT_Y)
phd_RotY_I(*(extra_rotation++));
if (poppush & ROT_X)
phd_RotX_I(*(extra_rotation++));
if (poppush & ROT_Z)
phd_RotZ_I(*(extra_rotation++));
}
bit <<= 1;
if (item->meshBits & bit)
phd_PutPolygons_I(*normal);
else
phd_PutPolygons_I(*statue);
}
}
}
PhdRight = PhdWidth;
PhdLeft = 0;
PhdTop = 0;
PhdBottom = PhdHeight;
phd_PopMatrix();
phd_PopDxMatrix();
}
void __cdecl InitialiseSwordGuardian(__int16 itemNum)
{
ANIM_STRUCT* anim;
ITEM_INFO* item;
item = &Items[itemNum];
item->animNumber = Objects[item->objectNumber].animIndex;
InitialiseCreature(itemNum);
anim = &Anims[item->animNumber];
item->frameNumber = anim->frameBase;
item->currentAnimState = anim->currentAnimState;
//item->status |= ITEM_INACTIVE;
item->status &= ~(ITEM_INVISIBLE);
item->meshBits = 0;
}
void __cdecl SwordGuardianFly(ITEM_INFO* item)
{
PHD_VECTOR pos;
pos.x = (GetRandomControl() << 8 >> 15) + item->pos.xPos - 128;
pos.y = (GetRandomControl() << 8 >> 15) + item->pos.yPos - 256;
pos.z = (GetRandomControl() << 8 >> 15) + item->pos.zPos - 128;
TriggerGunSmoke(pos.x, pos.y, pos.z, 1, 1, 1, 1, WEAPON_GRENADE_LAUNCHER, 32);
SoundEffect(SFX_SWORD_GUARDIAN_FLYING_ID312, &item->pos, 0);
}
void __cdecl SwordGuardianControl(__int16 itemNum)
{
if (!CreatureActive(itemNum))
return;
ITEM_INFO* item;
CREATURE_INFO* sword;
AI_INFO info;
short angle, head, torso;
bool lara_alive;
item = &Items[itemNum];
sword = (CREATURE_INFO*)item->data;
angle = head = torso = 0;
lara_alive = LaraItem->hitPoints > 0;
if (item->hitPoints <= 0)
{
item->meshBits >>= 1;
item->currentAnimState = 12;
if (!item->meshBits)
{
SoundEffect(105, NULL, 0);
item->meshBits = 0xFFFFFFFF;
item->objectNumber = ID_SAS;
ExplodingDeath(itemNum, -1, 256);
item->objectNumber = ID_SWAT;
DisableBaddieAI(itemNum);
KillItem(itemNum);
item->status = ITEM_DEACTIVATED;
item->flags |= ONESHOT;
}
return;
}
else
{
/* Get ground based information */
sword->LOT.step = STEP_SIZE;
sword->LOT.drop = -STEP_SIZE;
sword->LOT.fly = NO_FLYING;
sword->LOT.zone = 1;
CreatureAIInfo(item, &info);
if (item->currentAnimState == 8)
{
/* If flying and not in same zone, then use fly zone */
if (info.zoneNumber != info.enemyZone)
{
sword->LOT.step = WALL_SIZE * 20;
sword->LOT.drop = -WALL_SIZE * 20;
sword->LOT.fly = STEP_SIZE / 4;
sword->LOT.zone = 4;
CreatureAIInfo(item, &info);
}
}
GetCreatureMood(item, &info, VIOLENT);
CreatureMood(item, &info, VIOLENT);
angle = CreatureTurn(item, sword->maximumTurn);
if (item->currentAnimState != 9) // for reload
item->meshBits = 0xffffffff;
switch (item->currentAnimState)
{
case 9:
sword->maximumTurn = 0;
if (!sword->flags)
{
item->meshBits = (item->meshBits << 1) + 1;
sword->flags = 3;
}
else
{
sword->flags--;
}
break;
case 1:
sword->maximumTurn = 0;
if (info.ahead)
head = info.angle;
if (lara_alive)
{
if (info.bite && info.distance < 0x100000)
{
if (GetRandomControl() >= 0x4000)
item->goalAnimState = 5;
else
item->goalAnimState = 3;
}
else
{
if (info.zoneNumber == info.enemyZone)
item->goalAnimState = 2;
else
item->goalAnimState = 8;
}
}
else
{
item->goalAnimState = 7;
}
break;
case 2:
sword->maximumTurn = ANGLE(9);
if (info.ahead)
head = info.angle;
if (lara_alive)
{
if (info.bite && info.distance < 0x400000)
item->goalAnimState = 10;
else if (info.zoneNumber != info.enemyZone)
item->goalAnimState = 1;
}
else
{
item->goalAnimState = 1;
}
break;
case 3:
sword->flags = 0;
if (info.ahead)
torso = info.angle;
if (!info.bite || info.distance > 0x100000)
item->goalAnimState = 1;
else
item->goalAnimState = 4;
break;
case 5:
sword->flags = 0;
if (info.ahead)
torso = info.angle;
if (!info.bite || info.distance > 0x100000)
item->goalAnimState = 1;
else
item->goalAnimState = 6;
break;
case 10:
sword->flags = 0;
if (info.ahead)
torso = info.angle;
if (!info.bite || info.distance > 0x400000)
item->goalAnimState = 1;
else
item->goalAnimState = 11;
break;
case 8:
sword->maximumTurn = ANGLE(7);
if (info.ahead)
head = info.angle;
SwordGuardianFly(item);
if (!sword->LOT.fly)
item->goalAnimState = 1;
break;
case 4:
case 6:
case 11:
if (info.ahead)
torso = info.angle;
if (!sword->flags && (item->touchBits & 0xC000))
{
LaraItem->hitPoints -= 300;
LaraItem->hitStatus = true;
CreatureEffect(item, &swordBite, DoBloodSplat);
sword->flags = 1;
}
break;
}
}
if (item->hitPoints > 0)
{
CreatureJoint(item, 0, torso);
CreatureJoint(item, 1, head);
CreatureAnimation(itemNum, angle, 0);
}
}
void __cdecl InitialiseSpearGuardian(__int16 itemNum)
{
}
void __cdecl SpearGuardianControl(__int16 itemNum)
{
}
void __cdecl InitialiseShivaGuardian(__int16 itemNum)
{
}
void __cdecl ShivaGuardianControl(__int16 itemNum)
{
}