mirror of
https://github.com/TombEngine/TombEngine.git
synced 2025-05-13 05:57:05 +03:00
Merge branch 'master' into NewTRMath
This commit is contained in:
commit
e1ff9ba698
15 changed files with 1093 additions and 848 deletions
|
@ -8,30 +8,151 @@
|
|||
|
||||
BITE_INFO apeBite = { 0, -19, 75, 15 };
|
||||
|
||||
#define ATTACK_DAMAGE 200
|
||||
|
||||
#define TOUCH (0xFF00)
|
||||
|
||||
#define DIE_ANIM 7
|
||||
#define VAULT_ANIM 19
|
||||
|
||||
#define RUN_TURN ANGLE(5)
|
||||
|
||||
#define DISPLAY_ANGLE ANGLE(45)
|
||||
|
||||
#define ATTACK_RANGE SQUARE(430)
|
||||
#define PANIC_RANGE SQUARE(WALL_SIZE*2)
|
||||
|
||||
#define JUMP_CHANCE 0xa0
|
||||
#define WARN1_CHANCE (JUMP_CHANCE + 0xA0)
|
||||
#define WARN2_CHANCE (WARN1_CHANCE + 0xA0)
|
||||
#define RUNLEFT_CHANCE (WARN2_CHANCE + 0x110)
|
||||
|
||||
#define ATTACK_FLAG 1
|
||||
#define TURNL_FLAG 2
|
||||
#define TURNR_FLAG 4
|
||||
|
||||
#define SHIFT 75
|
||||
|
||||
enum ape_anims {
|
||||
APE_EMPTY,
|
||||
APE_STOP,
|
||||
APE_WALK,
|
||||
APE_RUN,
|
||||
APE_ATTACK1,
|
||||
APE_DEATH,
|
||||
APE_WARNING,
|
||||
APE_WARNING2,
|
||||
APE_RUNLEFT,
|
||||
APE_RUNRIGHT,
|
||||
APE_JUMP,
|
||||
APE_VAULT
|
||||
};
|
||||
|
||||
void ApeVault(short item_number, short angle)
|
||||
{
|
||||
ITEM_INFO *item;
|
||||
CREATURE_INFO *ape;
|
||||
long long y, xx, yy, x_floor, y_floor;
|
||||
short room_number;
|
||||
|
||||
item = &g_Level.Items[item_number];
|
||||
|
||||
ape = (CREATURE_INFO *)item->data;
|
||||
if (ape->flags & TURNL_FLAG)
|
||||
{
|
||||
item->pos.yRot -= 0x4000;
|
||||
ape->flags -= TURNL_FLAG;
|
||||
}
|
||||
else if (item->flags & TURNR_FLAG)
|
||||
{
|
||||
item->pos.yRot += 0x4000;
|
||||
ape->flags -= TURNR_FLAG;
|
||||
}
|
||||
|
||||
xx = item->pos.zPos >> WALL_SHIFT;
|
||||
yy = item->pos.xPos >> WALL_SHIFT;
|
||||
y = item->pos.yPos;
|
||||
room_number = item->roomNumber;
|
||||
|
||||
CreatureAnimation(item_number, angle, 0);
|
||||
|
||||
if (item->pos.yPos > y - STEP_SIZE * 3 / 2)
|
||||
return;
|
||||
|
||||
x_floor = item->pos.zPos >> WALL_SHIFT;
|
||||
y_floor = item->pos.xPos >> WALL_SHIFT;
|
||||
if (xx == x_floor)
|
||||
{
|
||||
if (yy == y_floor)
|
||||
return;
|
||||
|
||||
if (yy < y_floor)
|
||||
{
|
||||
item->pos.xPos = (y_floor << WALL_SHIFT) - SHIFT;
|
||||
item->pos.yRot = 0x4000;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->pos.xPos = (yy << WALL_SHIFT) + SHIFT;
|
||||
item->pos.yRot = -0x4000;
|
||||
}
|
||||
}
|
||||
else if (yy == y_floor)
|
||||
{
|
||||
if (xx < x_floor)
|
||||
{
|
||||
item->pos.zPos = (x_floor << WALL_SHIFT) - SHIFT;
|
||||
item->pos.yRot = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->pos.zPos = (xx << WALL_SHIFT) + SHIFT;
|
||||
item->pos.yRot = -0x8000;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// diagonal
|
||||
}
|
||||
|
||||
switch (CreatureVault(item_number, angle, 2, 75))
|
||||
{
|
||||
case 2:
|
||||
// creature->maximumTurn = 0;
|
||||
item->pos.yPos = y;
|
||||
item->animNumber = Objects[ID_APE].animIndex + VAULT_ANIM;
|
||||
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
||||
item->currentAnimState = APE_VAULT;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ApeControl(short itemNum)
|
||||
{
|
||||
short head, angle, random;
|
||||
|
||||
if (!CreatureActive(itemNum))
|
||||
return;
|
||||
|
||||
ITEM_INFO* item = &g_Level.Items[itemNum];
|
||||
CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
|
||||
|
||||
short head = 0;
|
||||
short angle = 0;
|
||||
short random = 0;
|
||||
AI_INFO info;
|
||||
head = angle = 0;
|
||||
|
||||
if (item->hitPoints <= 0)
|
||||
{
|
||||
if (item->currentAnimState != 5)
|
||||
if (item->currentAnimState != APE_DEATH)
|
||||
{
|
||||
item->animNumber = Objects[item->objectNumber].animIndex + 7 + (short)(GetRandomControl() / 0x4000);
|
||||
item->animNumber = Objects[item->objectNumber].animIndex + DIE_ANIM + (short)(GetRandomControl() / 0x4000);
|
||||
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
||||
item->currentAnimState = 5;
|
||||
item->currentAnimState = APE_DEATH;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AI_INFO info;
|
||||
CreatureAIInfo(item, &info);
|
||||
|
||||
if (info.ahead)
|
||||
|
@ -42,112 +163,112 @@ void ApeControl(short itemNum)
|
|||
|
||||
angle = CreatureTurn(item, creature->maximumTurn);
|
||||
|
||||
if (item->hitStatus || info.distance < SQUARE(2048))
|
||||
creature->flags |= 1;
|
||||
if (item->hitStatus || info.distance < PANIC_RANGE)
|
||||
creature->flags |= ATTACK_FLAG;
|
||||
|
||||
switch (item->currentAnimState)
|
||||
{
|
||||
case 1:
|
||||
if (creature->flags & 2)
|
||||
case APE_STOP:
|
||||
if (creature->flags & TURNL_FLAG)
|
||||
{
|
||||
item->pos.yRot -= ANGLE(90);
|
||||
creature->flags -= 2;
|
||||
creature->flags -= TURNL_FLAG;
|
||||
}
|
||||
else if (item->flags & 4)
|
||||
else if (item->flags & TURNR_FLAG)
|
||||
{
|
||||
item->pos.yRot += ANGLE(90);
|
||||
creature->flags -= 4;
|
||||
creature->flags -= TURNR_FLAG;
|
||||
}
|
||||
|
||||
if (item->requiredAnimState)
|
||||
item->goalAnimState = item->requiredAnimState;
|
||||
else if (info.bite && info.distance < SQUARE(430))
|
||||
item->goalAnimState = 4;
|
||||
else if (!(creature->flags & 1) &&
|
||||
else if (info.bite && info.distance < ATTACK_RANGE)
|
||||
item->goalAnimState = APE_ATTACK1;
|
||||
else if (!(creature->flags & ATTACK_FLAG) &&
|
||||
info.zoneNumber == info.enemyZone && info.ahead)
|
||||
{
|
||||
random = (short)(GetRandomControl() / 32);
|
||||
if (random < 0xA0)
|
||||
item->goalAnimState = 10;
|
||||
else if (random < 0x140)
|
||||
item->goalAnimState = 6;
|
||||
else if (random < 0x1E0)
|
||||
item->goalAnimState = 7;
|
||||
else if (random < 0x2F0)
|
||||
if (random < JUMP_CHANCE)
|
||||
item->goalAnimState = APE_JUMP;
|
||||
else if (random < WARN1_CHANCE)
|
||||
item->goalAnimState = APE_WARNING;
|
||||
else if (random < WARN2_CHANCE)
|
||||
item->goalAnimState = APE_WARNING2;
|
||||
else if (random < RUNLEFT_CHANCE)
|
||||
{
|
||||
item->goalAnimState = 8;
|
||||
item->goalAnimState = APE_RUNLEFT;
|
||||
creature->maximumTurn = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->goalAnimState = 9;
|
||||
item->goalAnimState = APE_RUNRIGHT;
|
||||
creature->maximumTurn = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
item->goalAnimState = 3;
|
||||
item->goalAnimState = APE_RUN;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
creature->maximumTurn = ANGLE(5);
|
||||
case APE_RUN:
|
||||
creature->maximumTurn = RUN_TURN;
|
||||
|
||||
if (creature->flags == 0 && info.angle > -ANGLE(45) && info.angle < ANGLE(45))
|
||||
item->goalAnimState = 1;
|
||||
else if (info.ahead && (item->touchBits & 0xFF00))
|
||||
if (creature->flags == 0 && info.angle > -DISPLAY_ANGLE && info.angle < DISPLAY_ANGLE)
|
||||
item->goalAnimState = APE_STOP;
|
||||
else if (info.ahead && (item->touchBits & TOUCH))
|
||||
{
|
||||
item->requiredAnimState = 4;
|
||||
item->goalAnimState = 1;
|
||||
item->requiredAnimState = APE_ATTACK1;
|
||||
item->goalAnimState = APE_STOP;
|
||||
}
|
||||
else if (creature->mood != ESCAPE_MOOD)
|
||||
{
|
||||
random = (short)GetRandomControl();
|
||||
if (random < 0xA0)
|
||||
if (random < JUMP_CHANCE)
|
||||
{
|
||||
item->requiredAnimState = 10;
|
||||
item->goalAnimState = 1;
|
||||
item->requiredAnimState = APE_JUMP;
|
||||
item->goalAnimState = APE_STOP;
|
||||
}
|
||||
else if (random < 0x140)
|
||||
else if (random < WARN1_CHANCE)
|
||||
{
|
||||
item->requiredAnimState = 6;
|
||||
item->goalAnimState = 1;
|
||||
item->requiredAnimState = APE_WARNING;
|
||||
item->goalAnimState = APE_STOP;
|
||||
}
|
||||
else if (random < 0x1E0)
|
||||
else if (random < WARN2_CHANCE)
|
||||
{
|
||||
item->requiredAnimState = 7;
|
||||
item->goalAnimState = 1;
|
||||
item->requiredAnimState = APE_WARNING2;
|
||||
item->goalAnimState = APE_STOP;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 8:
|
||||
if (!(creature->flags & 4))
|
||||
case APE_RUNLEFT:
|
||||
if (!(creature->flags & TURNR_FLAG))
|
||||
{
|
||||
item->pos.yRot -= ANGLE(90);
|
||||
creature->flags |= 4;
|
||||
creature->flags |= TURNR_FLAG;
|
||||
}
|
||||
|
||||
item->goalAnimState = 1;
|
||||
item->goalAnimState = APE_STOP;
|
||||
break;
|
||||
|
||||
case 9:
|
||||
if (!(creature->flags & 2))
|
||||
case APE_RUNRIGHT:
|
||||
if (!(creature->flags & TURNL_FLAG))
|
||||
{
|
||||
item->pos.yRot += ANGLE(90);
|
||||
creature->flags |= 2;
|
||||
creature->flags |= TURNL_FLAG;
|
||||
}
|
||||
|
||||
item->goalAnimState = 1;
|
||||
item->goalAnimState = APE_STOP;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if (!item->requiredAnimState && (item->touchBits & 0xFF00))
|
||||
case APE_ATTACK1:
|
||||
if (!item->requiredAnimState && (item->touchBits & TOUCH))
|
||||
{
|
||||
CreatureEffect(item, &apeBite, DoBloodSplat);
|
||||
|
||||
LaraItem->hitPoints -= 200;
|
||||
LaraItem->hitPoints -= ATTACK_DAMAGE;
|
||||
LaraItem->hitStatus = true;
|
||||
|
||||
item->requiredAnimState = 1;
|
||||
item->requiredAnimState = APE_STOP;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -155,32 +276,10 @@ void ApeControl(short itemNum)
|
|||
|
||||
CreatureJoint(item, 0, head);
|
||||
|
||||
if (item->currentAnimState != 11)
|
||||
if (item->currentAnimState != APE_VAULT)
|
||||
{
|
||||
if (creature->flags & 2)
|
||||
{
|
||||
item->pos.yRot -= ANGLE(90);
|
||||
creature->flags -= 2;
|
||||
}
|
||||
else if (item->flags & 4)
|
||||
{
|
||||
item->pos.yRot += ANGLE(90);
|
||||
creature->flags -= 4;
|
||||
}
|
||||
|
||||
switch (CreatureVault(itemNum, angle, 2, 75))
|
||||
{
|
||||
case 2:
|
||||
creature->maximumTurn = 0;
|
||||
item->animNumber = Objects[item->objectNumber].animIndex + 19;
|
||||
item->currentAnimState = 11;
|
||||
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
ApeVault(itemNum, angle);
|
||||
}
|
||||
else
|
||||
CreatureAnimation(itemNum, angle, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
void ApeControl(short itemNum);
|
||||
void ApeControl(short itemNum);
|
||||
|
|
|
@ -8,6 +8,40 @@
|
|||
|
||||
BITE_INFO bearBite = { 0, 96, 335, 14 };
|
||||
|
||||
enum bearStates{
|
||||
BEAR_STROLL,
|
||||
BEAR_STOP,
|
||||
BEAR_WALK,
|
||||
BEAR_RUN,
|
||||
BEAR_REAR,
|
||||
BEAR_ROAR,
|
||||
BEAR_ATTACK1,
|
||||
BEAR_ATTACK2,
|
||||
BEAR_EAT,
|
||||
BEAR_DEATH
|
||||
};
|
||||
#define TOUCH 0x2406C
|
||||
|
||||
|
||||
#define ROAR_CHANCE 0x50
|
||||
#define REAR_CHANCE 0x300
|
||||
#define DROP_CHANCE 0x600
|
||||
|
||||
#define REAR_RANGE SQUARE(WALL_SIZE*2)
|
||||
#define ATTACK_RANGE SQUARE(WALL_SIZE)
|
||||
#define PAT_RANGE SQUARE(600)
|
||||
|
||||
#define RUN_TURN ANGLE(5)
|
||||
#define WALK_TURN ANGLE(2)
|
||||
|
||||
#define EAT_RANGE SQUARE(WALL_SIZE*3/4)
|
||||
|
||||
|
||||
#define CHARGE_DAMAGE 3
|
||||
#define SLAM_DAMAGE 200
|
||||
#define ATTACK_DAMAGE 200
|
||||
#define PAT_DAMAGE 400
|
||||
|
||||
void BearControl(short itemNum)
|
||||
{
|
||||
if (!CreatureActive(itemNum))
|
||||
|
@ -17,48 +51,55 @@ void BearControl(short itemNum)
|
|||
CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
|
||||
|
||||
short head = 0;
|
||||
short angle = 0;
|
||||
short angle;
|
||||
|
||||
if (item->hitPoints <= 0)
|
||||
{
|
||||
if (item->currentAnimState != 9)
|
||||
{
|
||||
// if (item->currentAnimState != 9)
|
||||
// {
|
||||
angle = CreatureTurn(item, ANGLE(1));
|
||||
|
||||
switch (item->currentAnimState)
|
||||
{
|
||||
case 2:
|
||||
item->goalAnimState = 4;
|
||||
case BEAR_WALK:
|
||||
{
|
||||
item->goalAnimState = BEAR_REAR;
|
||||
break;
|
||||
case 3:
|
||||
case 0:
|
||||
item->goalAnimState = 1;
|
||||
}
|
||||
case BEAR_RUN:
|
||||
case BEAR_STROLL:
|
||||
{
|
||||
item->goalAnimState = BEAR_STOP;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
}
|
||||
case BEAR_REAR:
|
||||
{
|
||||
creature->flags = 1;
|
||||
item->goalAnimState = 9;
|
||||
item->goalAnimState = BEAR_DEATH;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
}
|
||||
case BEAR_STOP:
|
||||
{
|
||||
creature->flags = 0;
|
||||
item->goalAnimState = 9;
|
||||
item->goalAnimState = BEAR_DEATH;
|
||||
break;
|
||||
|
||||
case 9:
|
||||
if (creature->flags && (item->touchBits & 0x2406C))
|
||||
}
|
||||
case BEAR_DEATH:
|
||||
{
|
||||
if (creature->flags && (item->touchBits & TOUCH))
|
||||
{
|
||||
LaraItem->hitPoints -= 200;
|
||||
LaraItem->hitPoints -= SLAM_DAMAGE;
|
||||
LaraItem->hitStatus = 1;
|
||||
creature->flags = 0;
|
||||
}
|
||||
|
||||
item->animNumber = Objects[item->objectNumber].animIndex + 20;
|
||||
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
||||
item->currentAnimState = 9;
|
||||
// item->animNumber = Objects[item->objectNumber].animIndex + 20;
|
||||
// item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
||||
// item->currentAnimState = 9;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// }
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -76,18 +117,20 @@ void BearControl(short itemNum)
|
|||
if (item->hitStatus)
|
||||
creature->flags = 1;
|
||||
|
||||
const bool Laradead = (LaraItem->hitPoints <= 0);
|
||||
|
||||
switch (item->currentAnimState)
|
||||
{
|
||||
case 1:
|
||||
if (LaraItem->hitPoints <= 0)
|
||||
case BEAR_STOP:
|
||||
if (Laradead)
|
||||
{
|
||||
if (info.bite && info.distance < SQUARE(768))
|
||||
if (info.bite && info.distance < EAT_RANGE)
|
||||
{
|
||||
item->goalAnimState = 8;
|
||||
item->goalAnimState = BEAR_EAT;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->goalAnimState = 0;
|
||||
item->goalAnimState = BEAR_STROLL;
|
||||
}
|
||||
}
|
||||
else if (item->requiredAnimState)
|
||||
|
@ -96,70 +139,70 @@ void BearControl(short itemNum)
|
|||
}
|
||||
else if (creature->mood == BORED_MOOD)
|
||||
{
|
||||
item->goalAnimState = 0;
|
||||
item->goalAnimState = BEAR_STROLL;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->goalAnimState = 3;
|
||||
item->goalAnimState = BEAR_RUN;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0:
|
||||
creature->maximumTurn = ANGLE(2);
|
||||
case BEAR_STROLL:
|
||||
creature->maximumTurn = WALK_TURN;
|
||||
|
||||
if (LaraItem->hitPoints <= 0 && (item->touchBits & 0x2406C) && info.ahead)
|
||||
if (Laradead && (item->touchBits & TOUCH) && info.ahead)
|
||||
{
|
||||
item->goalAnimState = 1;
|
||||
item->goalAnimState = BEAR_STOP;
|
||||
}
|
||||
else if (creature->mood != BORED_MOOD)
|
||||
{
|
||||
item->goalAnimState = 1;
|
||||
item->goalAnimState = BEAR_STOP;
|
||||
if (creature->mood == ESCAPE_MOOD)
|
||||
{
|
||||
item->requiredAnimState = 0;
|
||||
item->requiredAnimState = BEAR_STROLL;
|
||||
}
|
||||
}
|
||||
else if (GetRandomControl() < 0x50)
|
||||
else if (GetRandomControl() < ROAR_CHANCE)
|
||||
{
|
||||
item->requiredAnimState = 5;
|
||||
item->goalAnimState = 1;
|
||||
item->requiredAnimState = BEAR_ROAR;
|
||||
item->goalAnimState = BEAR_STOP;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
creature->maximumTurn = ANGLE(5);
|
||||
case BEAR_RUN:
|
||||
creature->maximumTurn = RUN_TURN;
|
||||
|
||||
// if the bear slams you it hurts
|
||||
if (item->touchBits & 0x2406C)
|
||||
if (item->touchBits & TOUCH)
|
||||
{
|
||||
LaraItem->hitPoints -= 3;
|
||||
LaraItem->hitPoints -= CHARGE_DAMAGE;
|
||||
LaraItem->hitStatus = true;
|
||||
}
|
||||
|
||||
if (creature->mood == BORED_MOOD || LaraItem->hitPoints <= 0)
|
||||
if (creature->mood == BORED_MOOD || Laradead)
|
||||
{
|
||||
item->goalAnimState = 1;
|
||||
item->goalAnimState = BEAR_STOP;
|
||||
}
|
||||
else if (info.ahead && !item->requiredAnimState)
|
||||
{
|
||||
// bear may rear up, but not after he's taken some bullets!
|
||||
if (!creature->flags && info.distance < SQUARE(2048) && GetRandomControl() < 0x300)
|
||||
if (!creature->flags && info.distance < REAR_RANGE && GetRandomControl() < REAR_CHANCE)
|
||||
{
|
||||
item->requiredAnimState = 4;
|
||||
item->goalAnimState = 1;
|
||||
item->requiredAnimState = BEAR_REAR;
|
||||
item->goalAnimState = BEAR_STOP;
|
||||
}
|
||||
else if (info.distance < SQUARE(1024))
|
||||
else if (info.distance < ATTACK_RANGE)
|
||||
{
|
||||
item->goalAnimState = 6;
|
||||
item->goalAnimState = BEAR_ATTACK1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
case BEAR_REAR:
|
||||
if (creature->flags)
|
||||
{
|
||||
item->requiredAnimState = 0;
|
||||
item->goalAnimState = 1;
|
||||
item->requiredAnimState = BEAR_STROLL;
|
||||
item->goalAnimState = BEAR_STOP;
|
||||
}
|
||||
else if (item->requiredAnimState)
|
||||
{
|
||||
|
@ -167,62 +210,62 @@ void BearControl(short itemNum)
|
|||
}
|
||||
else if (creature->mood == BORED_MOOD || creature->mood == ESCAPE_MOOD)
|
||||
{
|
||||
item->goalAnimState = 1;
|
||||
item->goalAnimState = BEAR_STOP;
|
||||
}
|
||||
else if (info.bite && info.distance < SQUARE(600))
|
||||
else if (info.bite && info.distance < PAT_RANGE)
|
||||
{
|
||||
item->goalAnimState = 7;
|
||||
item->goalAnimState = BEAR_ATTACK2;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->goalAnimState = 2;
|
||||
item->goalAnimState = BEAR_WALK;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case BEAR_WALK:
|
||||
if (creature->flags)
|
||||
{
|
||||
item->requiredAnimState = 0;
|
||||
item->goalAnimState = 4;
|
||||
item->requiredAnimState = BEAR_STROLL;
|
||||
item->goalAnimState = BEAR_REAR;
|
||||
}
|
||||
else if (info.ahead && (item->touchBits & 0x2406C))
|
||||
else if (info.ahead && (item->touchBits & TOUCH))
|
||||
{
|
||||
item->goalAnimState = 4;
|
||||
item->goalAnimState = BEAR_REAR;
|
||||
}
|
||||
else if (creature->mood == ESCAPE_MOOD)
|
||||
{
|
||||
item->goalAnimState = 4;
|
||||
item->requiredAnimState = 0;
|
||||
item->goalAnimState = BEAR_REAR;
|
||||
item->requiredAnimState = BEAR_STROLL;
|
||||
}
|
||||
else if (creature->mood == BORED_MOOD || GetRandomControl() < 0x50)
|
||||
else if (creature->mood == BORED_MOOD || GetRandomControl() < ROAR_CHANCE)
|
||||
{
|
||||
item->requiredAnimState = 5;
|
||||
item->goalAnimState = 4;
|
||||
item->requiredAnimState = BEAR_ROAR;
|
||||
item->goalAnimState = BEAR_REAR;
|
||||
}
|
||||
else if (info.distance > SQUARE(2048) || GetRandomControl() < 0x600)
|
||||
else if (info.distance > REAR_RANGE || GetRandomControl() < DROP_CHANCE)
|
||||
{
|
||||
item->requiredAnimState = 1;
|
||||
item->goalAnimState = 4;
|
||||
item->requiredAnimState = BEAR_STOP;
|
||||
item->goalAnimState = BEAR_REAR;
|
||||
}
|
||||
break;
|
||||
|
||||
case 7:
|
||||
if (!item->requiredAnimState && (item->touchBits & 0x2406C))
|
||||
case BEAR_ATTACK2:
|
||||
if (!item->requiredAnimState && (item->touchBits & TOUCH))
|
||||
{
|
||||
LaraItem->hitPoints -= 400;
|
||||
LaraItem->hitPoints -= PAT_DAMAGE;
|
||||
LaraItem->hitStatus = true;
|
||||
item->requiredAnimState = 4;
|
||||
item->requiredAnimState = BEAR_REAR;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 6:
|
||||
if (!item->requiredAnimState && (item->touchBits & 0x2406C))
|
||||
case BEAR_ATTACK1:
|
||||
if (!item->requiredAnimState && (item->touchBits & TOUCH))
|
||||
{
|
||||
CreatureEffect(item, &bearBite, DoBloodSplat);
|
||||
LaraItem->hitPoints -= 200;
|
||||
LaraItem->hitPoints -= ATTACK_DAMAGE;
|
||||
LaraItem->hitStatus = true;
|
||||
item->requiredAnimState = 1;
|
||||
item->requiredAnimState = BEAR_STOP;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -231,4 +274,4 @@ void BearControl(short itemNum)
|
|||
|
||||
CreatureJoint(item, 0, head);
|
||||
CreatureAnimation(itemNum, angle, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
void BearControl(short itemNum);
|
||||
void BearControl(short itemNum);
|
||||
|
|
|
@ -24,10 +24,14 @@ void InitialiseDoppelganger(short itemNum)
|
|||
void DoppelgangerControl(short itemNum)
|
||||
{
|
||||
ITEM_INFO* item;
|
||||
ITEM_INFO* ref;
|
||||
FLOOR_INFO* floor;
|
||||
int h, lh;
|
||||
int x, y, z;
|
||||
short room_num;
|
||||
short xRef, zRef;
|
||||
|
||||
ref = find_a_fucking_item(ID_BACON_REFERENCE);
|
||||
|
||||
item = &g_Level.Items[itemNum];
|
||||
|
||||
|
@ -41,9 +45,11 @@ void DoppelgangerControl(short itemNum)
|
|||
{
|
||||
// TODO: fix evil lara moving.
|
||||
room_num = item->roomNumber;
|
||||
x = item->pos.xPos; // 2*36*WALL_SIZE - LaraItem->pos.xPos;
|
||||
y = item->pos.yPos; // LaraItem->pos.yPos;
|
||||
z = item->pos.zPos; // 2*60*WALL_SIZE - LaraItem->pos.zPos;
|
||||
xRef = ref->pos.xPos;
|
||||
zRef = ref->pos.zPos;
|
||||
x = 2 * ref->pos.xPos - LaraItem->pos.xPos;
|
||||
y = LaraItem->pos.yPos;
|
||||
z = 2 * ref->pos.zPos - LaraItem->pos.zPos;
|
||||
floor = GetFloor(x, y, z, &room_num);
|
||||
h = GetFloorHeight(floor, x, y, z);
|
||||
item->floor = h;
|
||||
|
@ -52,9 +58,9 @@ void DoppelgangerControl(short itemNum)
|
|||
lh = GetFloorHeight(floor, LaraItem->pos.xPos, LaraItem->pos.yPos, LaraItem->pos.zPos);
|
||||
item->frameNumber = LaraItem->frameNumber;
|
||||
item->animNumber = LaraItem->animNumber;
|
||||
//item->pos.xPos = x;
|
||||
//item->pos.yPos = y;
|
||||
//item->pos.zPos = z;
|
||||
item->pos.xPos = x;
|
||||
item->pos.yPos = y;
|
||||
item->pos.zPos = z;
|
||||
item->pos.xRot = LaraItem->pos.xRot;
|
||||
item->pos.yRot = LaraItem->pos.yRot - ANGLE(180);
|
||||
item->pos.zRot = LaraItem->pos.zRot;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
void InitialiseDoppelganger(short itemNum);
|
||||
void DoppelgangerControl(short itemNum);
|
||||
void DoppelgangerControl(short itemNum);
|
||||
|
|
|
@ -9,11 +9,47 @@
|
|||
|
||||
BITE_INFO wolfBite = { 0, -14, 174, 6 };
|
||||
|
||||
enum wolfStates {
|
||||
STATE_EMPTY,
|
||||
STATE_STOP,
|
||||
STATE_WALK,
|
||||
STATE_RUN,
|
||||
STATE_JUMP,
|
||||
STATE_STALK,
|
||||
STATE_ATTACK,
|
||||
STATE_HOWL,
|
||||
STATE_SLEEP,
|
||||
STATE_CROUCH,
|
||||
STATE_FASTTURN,
|
||||
STATE_DEATH,
|
||||
STATE_BITE
|
||||
};
|
||||
|
||||
#define TOUCH (0x774f)
|
||||
|
||||
#define SLEEP_FRAME 96
|
||||
|
||||
#define DIE_ANIM 20
|
||||
|
||||
#define ATTACK_RANGE SQUARE(WALL_SIZE*3/2)
|
||||
#define STALK_RANGE SQUARE(WALL_SIZE*3)
|
||||
|
||||
#define BITE_DAMAGE 100
|
||||
#define LUNGE_DAMAGE 50
|
||||
|
||||
#define WAKE_CHANCE 0x20
|
||||
#define SLEEP_CHANCE 0x20
|
||||
#define HOWL_CHANCE 0x180
|
||||
|
||||
#define WALK_TURN ANGLE(2)
|
||||
#define RUN_TURN ANGLE(5)
|
||||
#define STALK_TURN ANGLE(2)
|
||||
|
||||
void InitialiseWolf(short itemNum)
|
||||
{
|
||||
ITEM_INFO* item = &g_Level.Items[itemNum];
|
||||
ClearItem(itemNum);
|
||||
item->frameNumber = 96;
|
||||
item->frameNumber = SLEEP_FRAME;
|
||||
}
|
||||
|
||||
void WolfControl(short itemNum)
|
||||
|
@ -21,25 +57,26 @@ void WolfControl(short itemNum)
|
|||
if (!CreatureActive(itemNum))
|
||||
return;
|
||||
|
||||
short head;
|
||||
short angle;
|
||||
short tilt;
|
||||
|
||||
ITEM_INFO* item = &g_Level.Items[itemNum];
|
||||
CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
|
||||
|
||||
short head = 0;
|
||||
short angle = 0;
|
||||
short tilt = 0;
|
||||
head = angle = tilt = 0;
|
||||
AI_INFO info;
|
||||
|
||||
if (item->hitPoints <= 0)
|
||||
{
|
||||
if (item->currentAnimState != 11)
|
||||
if (item->currentAnimState != STATE_DEATH)
|
||||
{
|
||||
item->animNumber = Objects[item->objectNumber].animIndex + 20 + (short)(GetRandomControl() / 11000);
|
||||
item->animNumber = Objects[ID_WOLF].animIndex + DIE_ANIM + (short)(GetRandomControl() / 11000);
|
||||
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
||||
item->currentAnimState = 11;
|
||||
item->currentAnimState = STATE_DEATH;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AI_INFO info;
|
||||
CreatureAIInfo(item, &info);
|
||||
|
||||
if (info.ahead)
|
||||
|
@ -52,128 +89,128 @@ void WolfControl(short itemNum)
|
|||
|
||||
switch (item->currentAnimState)
|
||||
{
|
||||
case 8:
|
||||
case STATE_SLEEP:
|
||||
head = 0;
|
||||
|
||||
if (creature->mood == ESCAPE_MOOD || info.zoneNumber == info.enemyZone)
|
||||
{
|
||||
item->requiredAnimState = 9;
|
||||
item->goalAnimState = 1;
|
||||
item->requiredAnimState = STATE_CROUCH;
|
||||
item->goalAnimState = STATE_STOP;
|
||||
}
|
||||
else if (GetRandomControl() < 0x20)
|
||||
else if (GetRandomControl() < WAKE_CHANCE)
|
||||
{
|
||||
item->requiredAnimState = 2;
|
||||
item->goalAnimState = 1;
|
||||
item->requiredAnimState = STATE_WALK;
|
||||
item->goalAnimState = STATE_STOP;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case STATE_STOP:
|
||||
if (item->requiredAnimState)
|
||||
item->goalAnimState = item->requiredAnimState;
|
||||
else
|
||||
item->goalAnimState = 2;
|
||||
item->goalAnimState = STATE_WALK;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
creature->maximumTurn = ANGLE(2);
|
||||
case STATE_WALK:
|
||||
creature->maximumTurn = WALK_TURN;
|
||||
|
||||
if (creature->mood != BORED_MOOD)
|
||||
{
|
||||
item->goalAnimState = 5;
|
||||
item->requiredAnimState = 0;
|
||||
item->goalAnimState = STATE_STALK;
|
||||
item->requiredAnimState = STATE_EMPTY;
|
||||
}
|
||||
else if (GetRandomControl() < 0x20)
|
||||
else if (GetRandomControl() < SLEEP_CHANCE)
|
||||
{
|
||||
item->requiredAnimState = 8;
|
||||
item->goalAnimState = 1;
|
||||
item->requiredAnimState = STATE_SLEEP;
|
||||
item->goalAnimState = STATE_STOP;
|
||||
}
|
||||
break;
|
||||
|
||||
case 9:
|
||||
case STATE_CROUCH:
|
||||
if (item->requiredAnimState)
|
||||
item->goalAnimState = item->requiredAnimState;
|
||||
else if (creature->mood == ESCAPE_MOOD)
|
||||
item->goalAnimState = 3;
|
||||
item->goalAnimState = STATE_RUN;
|
||||
else if (info.distance < SQUARE(345) && info.bite)
|
||||
item->goalAnimState = 12;
|
||||
item->goalAnimState = STATE_BITE;
|
||||
else if (creature->mood == STALK_MOOD)
|
||||
item->goalAnimState = 5;
|
||||
item->goalAnimState = STATE_STALK;
|
||||
else if (creature->mood == BORED_MOOD)
|
||||
item->goalAnimState = 1;
|
||||
item->goalAnimState = STATE_STOP;
|
||||
else
|
||||
item->goalAnimState = 3;
|
||||
item->goalAnimState = STATE_RUN;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
creature->maximumTurn = ANGLE(2);
|
||||
case STATE_STALK:
|
||||
creature->maximumTurn = STALK_TURN;
|
||||
|
||||
if (creature->mood == ESCAPE_MOOD)
|
||||
item->goalAnimState = 3;
|
||||
item->goalAnimState = STATE_RUN;
|
||||
else if (info.distance < SQUARE(345) && info.bite)
|
||||
item->goalAnimState = 12;
|
||||
item->goalAnimState = STATE_BITE;
|
||||
else if (info.distance > SQUARE(3072))
|
||||
item->goalAnimState = 3;
|
||||
item->goalAnimState = STATE_RUN;
|
||||
else if (creature->mood == ATTACK_MOOD)
|
||||
{
|
||||
if (!info.ahead || info.distance > SQUARE(1536) ||
|
||||
(info.enemyFacing < FRONT_ARC && info.enemyFacing > -FRONT_ARC))
|
||||
item->goalAnimState = 3;
|
||||
item->goalAnimState = STATE_RUN;
|
||||
}
|
||||
else if (GetRandomControl() < 0x180)
|
||||
else if (GetRandomControl() < HOWL_CHANCE)
|
||||
{
|
||||
item->requiredAnimState = 7;
|
||||
item->goalAnimState = 9;
|
||||
item->requiredAnimState = STATE_HOWL;
|
||||
item->goalAnimState = STATE_CROUCH;
|
||||
}
|
||||
else if (creature->mood == BORED_MOOD)
|
||||
item->goalAnimState = 9;
|
||||
item->goalAnimState = STATE_CROUCH;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
creature->maximumTurn = ANGLE(5);
|
||||
creature->maximumTurn = RUN_TURN;
|
||||
tilt = angle;
|
||||
|
||||
if (info.ahead && info.distance < SQUARE(1536))
|
||||
if (info.ahead && info.distance < ATTACK_RANGE)
|
||||
{
|
||||
if (info.distance > (SQUARE(1536) / 2) &&
|
||||
if (info.distance > (ATTACK_RANGE / 2) &&
|
||||
(info.enemyFacing > FRONT_ARC || info.enemyFacing < -FRONT_ARC))
|
||||
{
|
||||
item->requiredAnimState = 5;
|
||||
item->goalAnimState = 9;
|
||||
item->requiredAnimState = STATE_STALK;
|
||||
item->goalAnimState = STATE_CROUCH;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->goalAnimState = 6;
|
||||
item->requiredAnimState = 0;
|
||||
item->goalAnimState = STATE_ATTACK;
|
||||
item->requiredAnimState = STATE_EMPTY;
|
||||
}
|
||||
}
|
||||
else if (creature->mood == STALK_MOOD && info.distance < SQUARE(3072))
|
||||
else if (creature->mood == STALK_MOOD && info.distance < STALK_RANGE)
|
||||
{
|
||||
item->requiredAnimState = 5;
|
||||
item->goalAnimState = 9;
|
||||
item->requiredAnimState = STATE_STALK;
|
||||
item->goalAnimState = STATE_CROUCH;
|
||||
}
|
||||
else if (creature->mood == BORED_MOOD)
|
||||
item->goalAnimState = 9;
|
||||
item->goalAnimState = STATE_CROUCH;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
case STATE_ATTACK:
|
||||
tilt = angle;
|
||||
if (!item->requiredAnimState && (item->touchBits & 0x774F))
|
||||
if (!item->requiredAnimState && (item->touchBits & TOUCH))
|
||||
{
|
||||
CreatureEffect(item, &wolfBite, DoBloodSplat);
|
||||
LaraItem->hitPoints -= 50;
|
||||
LaraItem->hitPoints -= LUNGE_DAMAGE;
|
||||
LaraItem->hitStatus = true;
|
||||
item->requiredAnimState = 3;
|
||||
item->requiredAnimState = STATE_RUN;
|
||||
}
|
||||
item->goalAnimState = 3;
|
||||
item->goalAnimState = STATE_RUN;
|
||||
break;
|
||||
|
||||
case 12:
|
||||
if (!item->requiredAnimState && (item->touchBits & 0x774F) && info.ahead)
|
||||
if (!item->requiredAnimState && (item->touchBits & TOUCH) && info.ahead)
|
||||
{
|
||||
CreatureEffect(item, &wolfBite, DoBloodSplat);
|
||||
LaraItem->hitPoints -= 100;
|
||||
LaraItem->hitPoints -= BITE_DAMAGE;
|
||||
LaraItem->hitStatus = true;
|
||||
item->requiredAnimState = 9;
|
||||
item->requiredAnimState = STATE_CROUCH;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -182,4 +219,4 @@ void WolfControl(short itemNum)
|
|||
CreatureTilt(item, tilt);
|
||||
CreatureJoint(item, 0, head);
|
||||
CreatureAnimation(itemNum, angle, tilt);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
void InitialiseWolf(short itemNum);
|
||||
void WolfControl(short itemNum);
|
||||
void WolfControl(short itemNum);
|
||||
|
|
|
@ -26,7 +26,7 @@ static void StartBaddy(OBJECT_INFO* obj)
|
|||
obj->initialise = InitialiseWolf;
|
||||
obj->control = WolfControl;
|
||||
obj->collision = CreatureCollision;
|
||||
obj->shadowSize = 128;
|
||||
obj->shadowSize = UNIT_SHADOW / 2;
|
||||
obj->hitPoints = 6;
|
||||
obj->pivotLength = 375;
|
||||
obj->radius = 340;
|
||||
|
@ -152,7 +152,13 @@ static void StartBaddy(OBJECT_INFO* obj)
|
|||
|
||||
static void StartObject(OBJECT_INFO* obj)
|
||||
{
|
||||
|
||||
obj = &Objects[ID_BACON_REFERENCE];
|
||||
if (obj->loaded)
|
||||
{
|
||||
obj->drawRoutine = nullptr;
|
||||
obj->collision = AIPickupCollision;
|
||||
obj->hitPoints = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void StartTrap(OBJECT_INFO* obj)
|
||||
|
|
|
@ -12,7 +12,18 @@
|
|||
|
||||
BITE_INFO TroopsBite1 = { 0, 300, 64, 7 };
|
||||
|
||||
|
||||
#define STATE_TROOPS_STOP 1
|
||||
#define STATE_TROOPS_WALK 2
|
||||
#define STATE_TROOPS_RUN 3
|
||||
#define STATE_TROOPS_ATTACK1 5
|
||||
#define STATE_TROOPS_ATTACK2 6
|
||||
#define STATE_TROOPS_DEATH 7
|
||||
#define STATE_TROOPS_AIM1 8
|
||||
#define STATE_TROOPS_AIM2 9
|
||||
#define STATE_TROOPS_AIM3 10
|
||||
#define STATE_TROOPS_ATTACK3 11
|
||||
#define STATE_TROOPS_KILLED_BY_SCORPION 15
|
||||
#define STATE_TROOPS_ATTACKED_BY_SCORPION 16
|
||||
|
||||
void InitialiseTroops(short itemNumber)
|
||||
{
|
||||
|
@ -22,12 +33,12 @@ void InitialiseTroops(short itemNumber)
|
|||
|
||||
if (item->triggerFlags == 1)
|
||||
{
|
||||
item->goalAnimState = item->currentAnimState = 16;
|
||||
item->goalAnimState = item->currentAnimState = STATE_TROOPS_ATTACKED_BY_SCORPION;
|
||||
item->animNumber = Objects[item->objectNumber].animIndex + 27;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->goalAnimState = item->currentAnimState = 1;
|
||||
item->goalAnimState = item->currentAnimState = STATE_TROOPS_STOP;
|
||||
item->animNumber = Objects[item->objectNumber].animIndex + 12;
|
||||
}
|
||||
|
||||
|
@ -39,18 +50,23 @@ void TroopsControl(short itemNumber)
|
|||
if (!CreatureActive(itemNumber))
|
||||
return;
|
||||
|
||||
&g_Level.Items[32].currentAnimState;
|
||||
|
||||
ITEM_INFO* item = &g_Level.Items[itemNumber];
|
||||
CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
|
||||
OBJECT_INFO* obj = &Objects[item->objectNumber];
|
||||
|
||||
short angle = 0;
|
||||
short tilt = 0;
|
||||
short joint0 = 0;
|
||||
short joint1 = 0;
|
||||
short joint2 = 0;
|
||||
short rot = 0;
|
||||
|
||||
int dx = 0;
|
||||
int dy = 0;
|
||||
int dz = 0;
|
||||
|
||||
int distance = 0;
|
||||
|
||||
if (item->firedWeapon)
|
||||
|
@ -69,14 +85,17 @@ void TroopsControl(short itemNumber)
|
|||
|
||||
if (item->hitPoints <= 0)
|
||||
{
|
||||
if (item->currentAnimState != 7 && item->currentAnimState != 15)
|
||||
if (item->currentAnimState != STATE_TROOPS_DEATH
|
||||
&& item->currentAnimState != STATE_TROOPS_KILLED_BY_SCORPION)
|
||||
{
|
||||
if (creature->enemy && creature->enemy->objectNumber == ID_BIG_SCORPION && (item->itemFlags[0] < 80))
|
||||
if (creature->enemy
|
||||
&& creature->enemy->objectNumber == ID_BIG_SCORPION
|
||||
&& item->itemFlags[0] < 80)
|
||||
{
|
||||
if (creature->enemy->animNumber == Objects[ID_BIG_SCORPION].animIndex + 6)
|
||||
{
|
||||
item->animNumber = Objects[item->objectNumber].animIndex + 23;
|
||||
if (item->currentAnimState == 16)
|
||||
if (item->currentAnimState == STATE_TROOPS_ATTACKED_BY_SCORPION)
|
||||
{
|
||||
item->frameNumber = g_Level.Anims[item->animNumber].frameBase += 37;
|
||||
}
|
||||
|
@ -84,8 +103,8 @@ void TroopsControl(short itemNumber)
|
|||
{
|
||||
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
||||
}
|
||||
item->goalAnimState = 15;
|
||||
item->currentAnimState = 15;
|
||||
item->goalAnimState = STATE_TROOPS_KILLED_BY_SCORPION;
|
||||
item->currentAnimState = STATE_TROOPS_KILLED_BY_SCORPION;
|
||||
|
||||
angle = 0;
|
||||
|
||||
|
@ -107,7 +126,7 @@ void TroopsControl(short itemNumber)
|
|||
else
|
||||
{
|
||||
item->animNumber = Objects[item->objectNumber].animIndex + 19;
|
||||
item->currentAnimState = 7;
|
||||
item->currentAnimState = STATE_TROOPS_DEATH;
|
||||
item->frameNumber = g_Level.Anims[item->frameNumber].frameBase;
|
||||
}
|
||||
}
|
||||
|
@ -137,7 +156,7 @@ void TroopsControl(short itemNumber)
|
|||
dx = currentItem->pos.xPos - item->pos.xPos;
|
||||
dy = currentItem->pos.yPos - item->pos.yPos;
|
||||
dz = currentItem->pos.zPos - item->pos.zPos;
|
||||
distance = dx * dx + dy * dy + dz * dz;
|
||||
distance = SQUARE(dx) + SQUARE(dy) + SQUARE(dz);
|
||||
|
||||
if (distance < minDistance)
|
||||
{
|
||||
|
@ -149,11 +168,10 @@ void TroopsControl(short itemNumber)
|
|||
}
|
||||
}
|
||||
|
||||
if (creature->hurtByLara && item->currentAnimState != 16)
|
||||
if (creature->hurtByLara && item->currentAnimState != STATE_TROOPS_ATTACKED_BY_SCORPION)
|
||||
creature->enemy = LaraItem;
|
||||
|
||||
AI_INFO info;
|
||||
|
||||
AI_INFO info;
|
||||
CreatureAIInfo(item, &info);
|
||||
|
||||
int distance = 0;
|
||||
|
@ -166,18 +184,20 @@ void TroopsControl(short itemNumber)
|
|||
{
|
||||
dx = LaraItem->pos.xPos - item->pos.xPos;
|
||||
dz = LaraItem->pos.zPos - item->pos.zPos;
|
||||
distance = dx * dx + dz * dz;
|
||||
distance = SQUARE(dx) + SQUARE(dz);
|
||||
rot = phd_atan(dz, dx) - item->pos.yRot;
|
||||
}
|
||||
|
||||
if (!creature->hurtByLara && creature->enemy == LaraItem)
|
||||
creature->enemy = NULL;
|
||||
|
||||
GetCreatureMood(item, &info, TIMID);
|
||||
CreatureMood(item, &info, TIMID);
|
||||
|
||||
// Vehicle handling
|
||||
if (Lara.Vehicle != NO_ITEM && info.bite)
|
||||
creature->mood == ESCAPE_MOOD;
|
||||
|
||||
CreatureMood(item, &info, TIMID);
|
||||
|
||||
angle = CreatureTurn(item, creature->maximumTurn);
|
||||
|
||||
if (item->hitStatus)
|
||||
|
@ -185,7 +205,7 @@ void TroopsControl(short itemNumber)
|
|||
|
||||
switch (item->currentAnimState)
|
||||
{
|
||||
case 1:
|
||||
case STATE_TROOPS_STOP:
|
||||
creature->flags = 0;
|
||||
creature->maximumTurn = 0;
|
||||
joint2 = rot;
|
||||
|
@ -194,7 +214,7 @@ void TroopsControl(short itemNumber)
|
|||
{
|
||||
if (abs(info.angle) >= ANGLE(10))
|
||||
{
|
||||
if ((info.angle & 0x8000u) == 0)
|
||||
if (info.angle >= 0)
|
||||
{
|
||||
item->pos.yRot += ANGLE(10);
|
||||
}
|
||||
|
@ -214,22 +234,22 @@ void TroopsControl(short itemNumber)
|
|||
joint2 = AIGuard(creature);
|
||||
if (!(byte)GetRandomControl())
|
||||
{
|
||||
if (item->currentAnimState == 1)
|
||||
if (item->currentAnimState == STATE_TROOPS_STOP)
|
||||
{
|
||||
item->goalAnimState = 4;
|
||||
break;
|
||||
}
|
||||
item->goalAnimState = 1;
|
||||
item->goalAnimState = STATE_TROOPS_STOP;
|
||||
}
|
||||
}
|
||||
else if (item->aiBits & PATROL1)
|
||||
{
|
||||
item->goalAnimState = 2;
|
||||
item->goalAnimState = STATE_TROOPS_WALK;
|
||||
joint2 = 0;
|
||||
}
|
||||
else if (creature->mood == ESCAPE_MOOD)
|
||||
{
|
||||
item->goalAnimState = 3;
|
||||
item->goalAnimState = STATE_TROOPS_RUN;
|
||||
}
|
||||
else if (Targetable(item, &info))
|
||||
{
|
||||
|
@ -237,16 +257,16 @@ void TroopsControl(short itemNumber)
|
|||
{
|
||||
if (GetRandomControl() >= 0x4000)
|
||||
{
|
||||
item->goalAnimState = 10;
|
||||
item->goalAnimState = STATE_TROOPS_AIM3;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->goalAnimState = 8;
|
||||
item->goalAnimState = STATE_TROOPS_AIM1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
item->goalAnimState = 2;
|
||||
item->goalAnimState = STATE_TROOPS_WALK;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -256,66 +276,67 @@ void TroopsControl(short itemNumber)
|
|||
{
|
||||
if (!creature->mood || info.distance <= SQUARE(2048))
|
||||
{
|
||||
item->goalAnimState = 2;
|
||||
item->goalAnimState = STATE_TROOPS_WALK;
|
||||
break;
|
||||
}
|
||||
item->goalAnimState = 3;
|
||||
item->goalAnimState = STATE_TROOPS_RUN;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->goalAnimState = 1;
|
||||
item->goalAnimState = STATE_TROOPS_STOP;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case STATE_TROOPS_WALK:
|
||||
creature->flags = 0;
|
||||
joint2 = rot;
|
||||
creature->maximumTurn = ANGLE(5);
|
||||
|
||||
if (item->aiBits & PATROL1)
|
||||
{
|
||||
item->goalAnimState = 2;
|
||||
item->goalAnimState = STATE_TROOPS_WALK;
|
||||
}
|
||||
else if (creature->mood == 2)
|
||||
else if (creature->mood == ESCAPE_MOOD)
|
||||
{
|
||||
item->goalAnimState = 3;
|
||||
item->goalAnimState = STATE_TROOPS_RUN;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((item->aiBits & GUARD) || (item->aiBits & GUARD) &&
|
||||
if ((item->aiBits & GUARD) || (item->aiBits & FOLLOW) &&
|
||||
(creature->reachedGoal || distance > SQUARE(2048)))
|
||||
{
|
||||
item->goalAnimState = 1;
|
||||
item->goalAnimState = STATE_TROOPS_STOP;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Targetable(item, &info))
|
||||
{
|
||||
if (info.distance < SQUARE(3072) || info.enemyZone != info.zoneNumber)
|
||||
{
|
||||
item->goalAnimState = 1;
|
||||
item->goalAnimState = STATE_TROOPS_STOP;
|
||||
break;
|
||||
}
|
||||
item->goalAnimState = 9;
|
||||
item->goalAnimState = STATE_TROOPS_AIM2;
|
||||
}
|
||||
else if (creature->mood)
|
||||
{
|
||||
if (info.distance > SQUARE(2048))
|
||||
{
|
||||
item->goalAnimState = 3;
|
||||
item->goalAnimState = STATE_TROOPS_RUN;
|
||||
}
|
||||
}
|
||||
else if (info.ahead)
|
||||
{
|
||||
item->goalAnimState = 1;
|
||||
item->goalAnimState = STATE_TROOPS_STOP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 3:
|
||||
case STATE_TROOPS_RUN:
|
||||
if (info.ahead)
|
||||
{
|
||||
joint2 = info.angle;
|
||||
|
@ -326,20 +347,21 @@ void TroopsControl(short itemNumber)
|
|||
if ((item->aiBits & GUARD) || (item->aiBits & FOLLOW) &&
|
||||
(creature->reachedGoal || distance > SQUARE(2048)))
|
||||
{
|
||||
item->goalAnimState = 2;
|
||||
item->goalAnimState = STATE_TROOPS_WALK;
|
||||
break;
|
||||
}
|
||||
|
||||
if (creature->mood != ESCAPE_MOOD)
|
||||
{
|
||||
if (Targetable(item, &info))
|
||||
{
|
||||
item->goalAnimState = 2;
|
||||
item->goalAnimState = STATE_TROOPS_WALK;
|
||||
break;
|
||||
}
|
||||
if (!creature->mood || creature->mood == STALK_MOOD &&
|
||||
if (creature->mood == BORED_MOOD || creature->mood == STALK_MOOD &&
|
||||
!(item->aiBits & FOLLOW) && info.distance < SQUARE(2048))
|
||||
{
|
||||
item->goalAnimState = 2;
|
||||
item->goalAnimState = STATE_TROOPS_WALK;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -355,22 +377,22 @@ void TroopsControl(short itemNumber)
|
|||
joint2 = AIGuard(creature);
|
||||
if (!(byte)GetRandomControl())
|
||||
{
|
||||
item->goalAnimState = 1;
|
||||
item->goalAnimState = STATE_TROOPS_STOP;
|
||||
}
|
||||
}
|
||||
else if (Targetable(item, &info))
|
||||
{
|
||||
item->goalAnimState = 5;
|
||||
item->goalAnimState = STATE_TROOPS_ATTACK1;
|
||||
}
|
||||
else if (creature->mood || !info.ahead)
|
||||
{
|
||||
item->goalAnimState = 1;
|
||||
item->goalAnimState = STATE_TROOPS_STOP;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 5:
|
||||
case 6:
|
||||
case STATE_TROOPS_ATTACK1:
|
||||
case STATE_TROOPS_ATTACK2:
|
||||
if (info.ahead)
|
||||
{
|
||||
joint0 = info.angle;
|
||||
|
@ -389,8 +411,8 @@ void TroopsControl(short itemNumber)
|
|||
|
||||
break;
|
||||
|
||||
case 8:
|
||||
case 10:
|
||||
case STATE_TROOPS_AIM1:
|
||||
case STATE_TROOPS_AIM3:
|
||||
creature->flags = 0;
|
||||
|
||||
if (info.ahead)
|
||||
|
@ -400,17 +422,17 @@ void TroopsControl(short itemNumber)
|
|||
|
||||
if (Targetable(item, &info))
|
||||
{
|
||||
item->goalAnimState = item->currentAnimState != 8 ? 11 : 5;
|
||||
item->goalAnimState = item->currentAnimState != STATE_TROOPS_AIM1 ? STATE_TROOPS_ATTACK1 : STATE_TROOPS_ATTACK3;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->goalAnimState = 1;
|
||||
item->goalAnimState = STATE_TROOPS_STOP;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 9:
|
||||
case STATE_TROOPS_AIM2:
|
||||
creature->flags = 0;
|
||||
|
||||
if (info.ahead)
|
||||
|
@ -420,23 +442,23 @@ void TroopsControl(short itemNumber)
|
|||
|
||||
if (Targetable(item, &info))
|
||||
{
|
||||
item->goalAnimState = 6;
|
||||
item->goalAnimState = STATE_TROOPS_ATTACK2;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->goalAnimState = 2;
|
||||
item->goalAnimState = STATE_TROOPS_WALK;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 11:
|
||||
if (item->goalAnimState != 1
|
||||
case STATE_TROOPS_ATTACK3:
|
||||
if (item->goalAnimState != STATE_TROOPS_STOP
|
||||
&& (creature->mood == ESCAPE_MOOD ||
|
||||
info.distance > SQUARE(3072) ||
|
||||
!Targetable(item, &info)))
|
||||
{
|
||||
item->goalAnimState = 1;
|
||||
item->goalAnimState = STATE_TROOPS_STOP;
|
||||
}
|
||||
|
||||
if (info.ahead)
|
||||
|
@ -457,11 +479,11 @@ void TroopsControl(short itemNumber)
|
|||
|
||||
break;
|
||||
|
||||
case 16:
|
||||
case STATE_TROOPS_ATTACKED_BY_SCORPION:
|
||||
creature->maximumTurn = 0;
|
||||
break;
|
||||
|
||||
case 17u:
|
||||
case 17:
|
||||
if (!WeaponEnemyTimer && !(GetRandomControl() & 0x7F))
|
||||
{
|
||||
item->goalAnimState = 4;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -22,6 +22,10 @@ void InitialiseRaisingBlock(short itemNumber)
|
|||
AddActiveItem(itemNumber);
|
||||
item->status = ITEM_ACTIVE;
|
||||
}
|
||||
|
||||
// Get height from animations
|
||||
ANIM_FRAME* frame = &g_Level.Frames[g_Level.Anims[Objects[item->objectNumber].animIndex].framePtr];
|
||||
item->itemFlags[7] = (short)abs(frame->boundingBox.Y1 - frame->boundingBox.Y2);
|
||||
}
|
||||
|
||||
void ControlRaisingBlock(short itemNumber)
|
||||
|
@ -36,20 +40,20 @@ void ControlRaisingBlock(short itemNumber)
|
|||
{
|
||||
if (item->triggerFlags == -1)
|
||||
{
|
||||
AlterFloorHeight(item, -255);
|
||||
//AlterFloorHeight(item, -255);
|
||||
}
|
||||
else if (item->triggerFlags == -3)
|
||||
{
|
||||
AlterFloorHeight(item, -1023);
|
||||
//AlterFloorHeight(item, -1023);
|
||||
}
|
||||
else
|
||||
{
|
||||
AlterFloorHeight(item, -1024);
|
||||
//AlterFloorHeight(item, -item->itemFlags[7]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AlterFloorHeight(item, -2048);
|
||||
//AlterFloorHeight(item, -item->itemFlags[7]);
|
||||
}
|
||||
|
||||
item->itemFlags[2] = 1;
|
||||
|
@ -89,22 +93,22 @@ void ControlRaisingBlock(short itemNumber)
|
|||
{
|
||||
if (item->triggerFlags == -1)
|
||||
{
|
||||
AlterFloorHeight(item, 255);
|
||||
//AlterFloorHeight(item, 255);
|
||||
item->itemFlags[2] = 0;
|
||||
}
|
||||
else if (item->triggerFlags == -3)
|
||||
{
|
||||
AlterFloorHeight(item, 1023);
|
||||
//AlterFloorHeight(item, 1023);
|
||||
item->itemFlags[2] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
AlterFloorHeight(item, 1024);
|
||||
//AlterFloorHeight(item, item->itemFlags[7]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AlterFloorHeight(item, 2048);
|
||||
//AlterFloorHeight(item, item->itemFlags[7]);
|
||||
}
|
||||
|
||||
item->itemFlags[2] = 0;
|
||||
|
@ -129,4 +133,26 @@ void ControlRaisingBlock(short itemNumber)
|
|||
|
||||
item->itemFlags[1] -= 64;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::tuple<std::optional<int>, bool> RaisingBlockFloor(short itemNumber, int x, int y, int z)
|
||||
{
|
||||
const auto& item = g_Level.Items[itemNumber];
|
||||
if (abs(item.pos.xPos - x) <= SECTOR(1) / 2 && abs(item.pos.zPos - z) <= SECTOR(1) / 2)
|
||||
{
|
||||
auto height = item.pos.yPos - item.itemFlags[7] * item.itemFlags[1] / 4096;
|
||||
return std::make_tuple(std::optional{height}, y > height && y < item.pos.yPos);
|
||||
}
|
||||
return std::make_tuple(std::nullopt, false);
|
||||
}
|
||||
|
||||
std::tuple<std::optional<int>, bool> RaisingBlockCeiling(short itemNumber, int x, int y, int z)
|
||||
{
|
||||
const auto& item = g_Level.Items[itemNumber];
|
||||
if (abs(item.pos.xPos - x) <= SECTOR(1) / 2 && abs(item.pos.zPos - z) <= SECTOR(1) / 2)
|
||||
{
|
||||
auto height = item.pos.yPos - item.itemFlags[7] * item.itemFlags[1] / 4096;
|
||||
return std::make_tuple(std::optional{item.pos.yPos}, y > height && y < item.pos.yPos);
|
||||
}
|
||||
return std::make_tuple(std::nullopt, false);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
void InitialiseRaisingBlock(short itemNumber);
|
||||
void ControlRaisingBlock(short itemNumber);
|
||||
void ControlRaisingBlock(short itemNumber);
|
||||
std::tuple<std::optional<int>, bool> RaisingBlockFloor(short itemNumber, int x, int y, int z);
|
||||
std::tuple<std::optional<int>, bool> RaisingBlockCeiling(short itemNumber, int x, int y, int z);
|
||||
|
|
|
@ -903,6 +903,8 @@ static void StartObject(OBJECT_INFO *obj)
|
|||
{
|
||||
obj->initialise = InitialiseRaisingBlock;
|
||||
obj->control = ControlRaisingBlock;
|
||||
obj->floor = RaisingBlockFloor;
|
||||
obj->ceiling = RaisingBlockCeiling;
|
||||
obj->saveFlags = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -805,6 +805,7 @@ typedef enum GAME_OBJECT_ID
|
|||
ID_WATERFALLSS1,
|
||||
ID_WATERFALLSS2,
|
||||
ID_FISHTANK,
|
||||
ID_BACON_REFERENCE,
|
||||
|
||||
ID_MESHSWAP1 = 1100,
|
||||
ID_MESHSWAP2,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue