TombEngine/TR5Main/Objects/TR3/tr3_shiva.cpp
TokyoSU 7432353bed Restructured the Entity Files
- Moved GetWaterSurface to Control.cpp.
- Added mineL/mineR in LaraExtraInfo.
2019-12-05 17:35:57 +01:00

411 lines
No EOL
9 KiB
C++

#include "../newobjects.h"
#include "../../Game/effect2.h"
#include "../../Game/Box.h"
#include "../../Game/effects.h"
#include "../../Game/sphere.h"
BITE_INFO shivaLeftBite = { 0, 0, 920, 13 };
BITE_INFO shivaRightBite = { 0, 0, 920, 22 };
void TriggerShivaSmoke(long x, long y, long z, long uw)
{
long size;
SPARKS* sptr;
long dx, dz;
dx = LaraItem->pos.xPos - x;
dz = LaraItem->pos.zPos - z;
if (dx < -0x4000 || dx > 0x4000 || dz < -0x4000 || dz > 0x4000)
return;
sptr = &Sparks[GetFreeSpark()];
sptr->on = 1;
if (uw)
{
sptr->sR = 0;
sptr->sG = 0;
sptr->sB = 0;
sptr->dR = 192;
sptr->dG = 192;
sptr->dB = 208;
}
else
{
sptr->sR = 144;
sptr->sG = 144;
sptr->sB = 144;
sptr->dR = 64;
sptr->dG = 64;
sptr->dB = 64;
}
sptr->colFadeSpeed = 8;
sptr->fadeToBlack = 64;
sptr->sLife = sptr->life = (GetRandomControl() & 31) + 96;
if (uw)
sptr->transType = 2;
else
sptr->transType = 2;
sptr->extras = 0;
sptr->dynamic = -1;
sptr->x = x + (GetRandomControl() & 31) - 16;
sptr->y = y + (GetRandomControl() & 31) - 16;
sptr->z = z + (GetRandomControl() & 31) - 16;
sptr->xVel = ((GetRandomControl() & 4095) - 2048) >> 2;
sptr->yVel = (GetRandomControl() & 255) - 128;
sptr->zVel = ((GetRandomControl() & 4095) - 2048) >> 2;
if (uw)
{
sptr->yVel >>= 4;
sptr->y += 32;
sptr->friction = 4 | (1 << 4);
}
else
{
sptr->friction = 6;
}
sptr->flags = SP_SCALE | SP_DEF | SP_ROTATE | SP_EXPDEF;
sptr->rotAng = GetRandomControl() & 4095;
if (GetRandomControl() & 1)
sptr->rotAdd = -(GetRandomControl() & 15) - 16;
else
sptr->rotAdd = (GetRandomControl() & 15) + 16;
sptr->scalar = 3;
if (uw)
{
sptr->gravity = sptr->maxYvel = 0;
}
else
{
sptr->gravity = -(GetRandomControl() & 3) - 3;
sptr->maxYvel = -(GetRandomControl() & 3) - 4;
}
size = (GetRandomControl() & 31) + 128;
sptr->size = sptr->sSize = size >> 2;
sptr->dSize = size;
size += (GetRandomControl() & 31) + 32;
sptr->size = sptr->sSize = size >> 3;
sptr->dSize = size;
}
void ShivaDamage(ITEM_INFO* item, CREATURE_INFO* shiva, int damage)
{
if (!(shiva->flags) && (item->touchBits & 0x2400000))
{
LaraItem->hitPoints -= damage;
LaraItem->hitStatus = true;
CreatureEffect(item, &shivaRightBite, DoBloodSplat);
shiva->flags = 1;
SoundEffect(SFX_TR2_SWORD_HITTARGET_ID318, &item->pos, 0);
}
if (!(shiva->flags) && (item->touchBits & 0x2400))
{
LaraItem->hitPoints -= damage;
LaraItem->hitStatus = true;
CreatureEffect(item, &shivaLeftBite, DoBloodSplat);
shiva->flags = 1;
SoundEffect(SFX_TR2_SWORD_HITTARGET_ID318, &item->pos, 0);
}
}
void InitialiseShiva(short itemNum)
{
ANIM_STRUCT* anim;
ITEM_INFO* item;
InitialiseCreature(itemNum);
item = &Items[itemNum];
item->animNumber = Objects[item->objectNumber].animIndex + 14;
anim = &Anims[item->animNumber];
item->frameNumber = anim->frameBase;
item->currentAnimState = anim->currentAnimState;
//item->status = ITEM_INACTIVE;
//item->meshBits = 0;
}
void ShivaControl(short itemNum)
{
if (!CreatureActive(itemNum))
return;
ITEM_INFO* item;
CREATURE_INFO* shiva;
short angle, head_x, head_y, torso_x, torso_y, tilt, room_number;
int x, z;
int random, lara_alive;
AI_INFO info;
PHD_VECTOR pos;
FLOOR_INFO* floor;
int effect_mesh = 0;
item = &Items[itemNum];
shiva = (CREATURE_INFO*)item->data;
head_x = head_y = torso_x = torso_y = angle = tilt = 0;
lara_alive = (LaraItem->hitPoints > 0);
pos.x = 0; // Copy Offsets from mesh
pos.y = 0; // Pivot
pos.z = 256;
if (item->hitPoints <= 0)
{
if (item->currentAnimState != 9)
{
item->animNumber = Objects[item->objectNumber].animIndex + 22;
item->frameNumber = Anims[item->animNumber].frameBase;
item->currentAnimState = 9;
}
}
else
{
CreatureAIInfo(item, &info);
GetCreatureMood(item, &info, VIOLENT);
CreatureMood(item, &info, VIOLENT);
if (shiva->mood == ESCAPE_MOOD)
{
shiva->target.x = LaraItem->pos.xPos;
shiva->target.z = LaraItem->pos.zPos;
}
angle = CreatureTurn(item, shiva->maximumTurn);
if (item->currentAnimState != 4)
item->meshBits = 0xFFFFFFFF;
switch (item->currentAnimState)
{
case 4:
shiva->maximumTurn = 0;
if (!shiva->flags)
{
if (item->meshBits == 0)
effect_mesh = 0;
item->meshBits = (item->meshBits << 1) + 1;
shiva->flags = 1;
GetJointAbsPosition(item, &pos, effect_mesh++);
TriggerExplosionSparks(pos.x, pos.y, pos.z, 2, 0, 0, item->roomNumber);
TriggerShivaSmoke(pos.x, pos.y, pos.z, 1);
}
else
{
shiva->flags--;
}
if (item->meshBits == 0x7FFFFFFF)
{
item->goalAnimState = 0;
effect_mesh = 0;
shiva->flags = -45; //set up the delay before actually moving
}
break;
case 0:
if (info.ahead)
head_y = info.angle;
if (shiva->flags < 0) //delay before moving
{
shiva->flags++;
TriggerShivaSmoke(item->pos.xPos + (GetRandomControl() & 0x5FF) - 0x300, pos.y - (GetRandomControl() & 0x5FF), item->pos.zPos + (GetRandomControl() & 0x5FF) - 0x300, 1);
break;
}
if (shiva->flags == 1)
shiva->flags = 0;
shiva->maximumTurn = 0;
if (shiva->mood == ESCAPE_MOOD)
{
room_number = item->roomNumber;
x = item->pos.xPos + (WALL_SIZE * SIN(item->pos.yRot + 0x8000) >> W2V_SHIFT);
z = item->pos.zPos + (WALL_SIZE * COS(item->pos.yRot + 0x8000) >> W2V_SHIFT);
floor = GetFloor(x, item->pos.yPos, z, &room_number);
if (!shiva->flags && floor->box != NO_BOX && !(Boxes[floor->box].overlapIndex & BLOCKABLE))
item->goalAnimState = 8;
else
item->goalAnimState = 2;
}
else if (shiva->mood == BORED_MOOD)
{
random = GetRandomControl();
if (random < 0x400)
item->goalAnimState = 1;
}
else if (info.bite && info.distance < SQUARE(WALL_SIZE * 5 / 4))
{
item->goalAnimState = 5;
shiva->flags = 0;
}
else if (info.bite && info.distance < SQUARE(WALL_SIZE * 4 / 3))
{
item->goalAnimState = 7;
shiva->flags = 0;
}
else if (item->hitStatus && info.ahead)
{
shiva->flags = 4;
item->goalAnimState = 2;
}
else
{
item->goalAnimState = 1;
}
break;
case 2:
if (info.ahead)
head_y = info.angle;
shiva->maximumTurn = 0;
if (item->hitStatus || shiva->mood == ESCAPE_MOOD)
shiva->flags = 4;
if ((info.bite && info.distance < SQUARE(WALL_SIZE * 4 / 3)) || (item->frameNumber == Anims[item->animNumber].frameBase && !shiva->flags) || !info.ahead)
{
item->goalAnimState = 0;
shiva->flags = 0;
}
else if (shiva->flags)
{
item->goalAnimState = 2;
}
if (item->frameNumber == Anims[item->animNumber].frameBase && shiva->flags > 1)
shiva->flags -= 2;
break;
case 1:
if (info.ahead)
head_y = info.angle;
shiva->maximumTurn = ANGLE(4);
if (shiva->mood == ESCAPE_MOOD)
{
item->goalAnimState = 0;
}
else if (shiva->mood == BORED_MOOD)
{
item->goalAnimState = 0;
}
else if (info.bite && info.distance < SQUARE(WALL_SIZE * 4 / 3))
{
item->goalAnimState = 0;
shiva->flags = 0;
}
else if (item->hitStatus)
{
shiva->flags = 4;
item->goalAnimState = 3;
}
break;
case 3:
if (info.ahead)
head_y = info.angle;
shiva->maximumTurn = ANGLE(4);
if (item->hitStatus)
shiva->flags = 4;
if ((info.bite && info.distance < SQUARE(WALL_SIZE * 5 / 4)) || (item->frameNumber == Anims[item->animNumber].frameBase && !shiva->flags))
{
item->goalAnimState = 1;
shiva->flags = 0;
}
else if (shiva->flags)
{
item->goalAnimState = 3;
}
if (item->frameNumber == Anims[item->animNumber].frameBase)
{
shiva->flags = 0;
}
break;
case 8:
if (info.ahead)
head_y = info.angle;
shiva->maximumTurn = ANGLE(4);
if ((info.ahead && info.distance < SQUARE(WALL_SIZE * 4 / 3)) || (item->frameNumber == Anims[item->animNumber].frameBase && !shiva->flags))
{
item->goalAnimState = 0;
}
else if (item->hitStatus)
{
shiva->flags = 4;
item->goalAnimState = 0;
}
break;
case 5:
if (info.ahead)
{
torso_y = info.angle;
torso_x = info.xAngle;
head_y = info.angle;
}
shiva->maximumTurn = ANGLE(4);
ShivaDamage(item, shiva, 150);
break;
case 7:
torso_y = info.angle;
head_y = info.angle;
if (info.xAngle > 0)
torso_x = info.xAngle;
shiva->maximumTurn = ANGLE(4);
ShivaDamage(item, shiva, 180);
break;
case 6:
torso_y = torso_x = head_x = head_y = shiva->maximumTurn = 0;
if (item->frameNumber == Anims[item->animNumber].frameBase + 10 || item->frameNumber == Anims[item->animNumber].frameBase + 21 || item->frameNumber == Anims[item->animNumber].frameBase + 33)
{
CreatureEffect(item, &shivaRightBite, DoBloodSplat);
CreatureEffect(item, &shivaLeftBite, DoBloodSplat);
}
break;
}
}
if (lara_alive && LaraItem->hitPoints <= 0)
{
CreatureKill(item, 18, 6, 2); // uses EXTRA_YETIKILL slot
return;
}
CreatureTilt(item, tilt);
head_y -= torso_y;
CreatureJoint(item, 0, torso_y);
CreatureJoint(item, 1, torso_x);
CreatureJoint(item, 2, head_y);
CreatureJoint(item, 3, head_x);
CreatureAnimation(itemNum, angle, tilt);
}