Fixed enemy monkey; Added new zone for ID_VON_CROY; Small AI fixes; Added 3 blocks jump;

This commit is contained in:
Montagna Marco 2020-09-01 07:06:31 +02:00
parent b987e9bda8
commit 82af97c8cc
9 changed files with 236 additions and 478 deletions

View file

@ -25,6 +25,7 @@ typedef enum ZoneType
ZONE_BASIC, ZONE_BASIC,
ZONE_FLYER, ZONE_FLYER,
ZONE_HUMAN_CLASSIC, ZONE_HUMAN_CLASSIC,
ZONE_VON_CROY,
ZONE_WATER, ZONE_WATER,
ZONE_MAX, ZONE_MAX,
/// custom zone (using zone above for LOT.zone): /// custom zone (using zone above for LOT.zone):
@ -34,6 +35,7 @@ typedef enum ZoneType
ZONE_BLOCKABLE, // for trex, shiva, etc.. ZONE_BLOCKABLE, // for trex, shiva, etc..
ZONE_SOPHIALEE, // dont want sophia to go down again ! ZONE_SOPHIALEE, // dont want sophia to go down again !
ZONE_APE, // only 2 click climb ZONE_APE, // only 2 click climb
ZONE_HUMAN_LONGJUMP_AND_MONKEY,
}; };
typedef struct OBJECT_Bones typedef struct OBJECT_Bones

View file

@ -1009,7 +1009,7 @@ int SearchLOT(LOT_INFO* LOT, int depth)
continue; continue;
delta = g_Level.Boxes[boxNumber].height - box->height; delta = g_Level.Boxes[boxNumber].height - box->height;
if (delta > LOT->step || delta < LOT->drop) if ((delta > LOT->step || delta < LOT->drop) && !((flags & BOX_MONKEY) && LOT->canMonkey))
continue; continue;
expand = &LOT->node[boxNumber]; expand = &LOT->node[boxNumber];
@ -1587,6 +1587,8 @@ void CreatureMood(ITEM_INFO* item, AI_INFO* info, int violent)
do do
{ {
//overlapIndex++; //overlapIndex++;
//if (g_Level.Overlaps[overlapIndex++].flags & (BOX_JUMP|BOX_MONKEY))
//{
nextBox = g_Level.Overlaps[overlapIndex].box; nextBox = g_Level.Overlaps[overlapIndex].box;
flags = g_Level.Overlaps[overlapIndex++].flags; flags = g_Level.Overlaps[overlapIndex++].flags;
} while (nextBox != NO_BOX && ((flags & BOX_END_BIT) == FALSE) && (nextBox != startBox)); } while (nextBox != NO_BOX && ((flags & BOX_END_BIT) == FALSE) && (nextBox != startBox));

View file

@ -239,6 +239,15 @@ void InitialiseSlot(short itemNum, short slot)
creature->LOT.zone = ZONE_HUMAN_CLASSIC; creature->LOT.zone = ZONE_HUMAN_CLASSIC;
break; break;
case ZONE_HUMAN_LONGJUMP_AND_MONKEY:
// Can climb, jump, monkey, long jump
creature->LOT.step = SECTOR(1);
creature->LOT.drop = -SECTOR(1);
creature->LOT.canJump = true;
creature->LOT.canMonkey = true;
creature->LOT.zone = ZONE_VON_CROY;
break;
case ZONE_SPIDER: case ZONE_SPIDER:
creature->LOT.step = SECTOR(1) - CLICK(2); creature->LOT.step = SECTOR(1) - CLICK(2);
creature->LOT.drop = -(SECTOR(1) - CLICK(2)); creature->LOT.drop = -(SECTOR(1) - CLICK(2));

View file

@ -12,6 +12,11 @@
#include "lara.h" #include "lara.h"
#include "sound.h" #include "sound.h"
#define STATE_GUIDE_STOP 1
#define STATE_GUIDE_WALK 2
#define STATE_GUIDE_RUN 3
#define STATE_GUIDE_IGNITE_TORCH 11
BITE_INFO guideBiteInfo1 = { 0, 20, 200, 18 }; BITE_INFO guideBiteInfo1 = { 0, 20, 200, 18 };
BITE_INFO guideBiteInfo2 = { 30, 80, 50, 15 }; BITE_INFO guideBiteInfo2 = { 30, 80, 50, 15 };
@ -23,8 +28,8 @@ void InitialiseGuide(short itemNumber)
item->animNumber = Objects[item->objectNumber].animIndex + 4; item->animNumber = Objects[item->objectNumber].animIndex + 4;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = 1; item->goalAnimState = STATE_GUIDE_STOP;
item->currentAnimState = 1; item->currentAnimState = STATE_GUIDE_STOP;
item->swapMeshFlags = 0x40000; item->swapMeshFlags = 0x40000;
} }
@ -124,6 +129,7 @@ void GuideControl(short itemNumber)
ITEM_INFO* currentItem = &g_Level.Items[baddie->itemNum]; ITEM_INFO* currentItem = &g_Level.Items[baddie->itemNum];
if (currentItem->objectNumber != ID_GUIDE && if (currentItem->objectNumber != ID_GUIDE &&
currentItem->objectNumber != ID_VON_CROY &&
abs(currentItem->pos.yPos - item->pos.yPos) <= 512) abs(currentItem->pos.yPos - item->pos.yPos) <= 512)
{ {
dx = currentItem->pos.xPos - item->pos.xPos; dx = currentItem->pos.xPos - item->pos.xPos;
@ -173,7 +179,7 @@ void GuideControl(short itemNumber)
switch (item->currentAnimState) switch (item->currentAnimState)
{ {
case 1: case STATE_GUIDE_STOP:
creature->LOT.isJumping = false; creature->LOT.isJumping = false;
creature->flags = 0; creature->flags = 0;
creature->maximumTurn = 0; creature->maximumTurn = 0;
@ -195,7 +201,7 @@ void GuideControl(short itemNumber)
/*if (Objects[ID_WRAITH1].loaded & 0x10000) /*if (Objects[ID_WRAITH1].loaded & 0x10000)
{ {
if (item->itemFlags[3] == 5) if (item->itemFlags[3] == 5)
item->goalAnimState = 2; item->goalAnimState = STATE_GUIDE_WALK;
if (item->itemFlags[3] == 5 || item->itemFlags[3] == 6) if (item->itemFlags[3] == 5 || item->itemFlags[3] == 6)
{ {
@ -232,7 +238,7 @@ void GuideControl(short itemNumber)
} }
else if (/*true ||*/ enemy != LaraItem || info.distance > SQUARE(2048)) else if (/*true ||*/ enemy != LaraItem || info.distance > SQUARE(2048))
{ {
item->goalAnimState = 2; item->goalAnimState = STATE_GUIDE_WALK;
} }
} }
else else
@ -309,12 +315,12 @@ void GuideControl(short itemNumber)
} }
else else
{ {
item->goalAnimState = 1; item->goalAnimState = STATE_GUIDE_STOP;
} }
break; break;
case 2: case STATE_GUIDE_WALK:
creature->LOT.isJumping = false; creature->LOT.isJumping = false;
creature->maximumTurn = ANGLE(7); creature->maximumTurn = ANGLE(7);
@ -333,8 +339,8 @@ void GuideControl(short itemNumber)
if (item->itemFlags[1] == 1) if (item->itemFlags[1] == 1)
{ {
item->goalAnimState = 1; item->goalAnimState = STATE_GUIDE_STOP;
item->requiredAnimState = 11; // Ignite torch item->requiredAnimState = STATE_GUIDE_IGNITE_TORCH; // Ignite torch
} }
else if (creature->reachedGoal) else if (creature->reachedGoal)
{ {
@ -347,7 +353,7 @@ void GuideControl(short itemNumber)
break; break;
} }
item->goalAnimState = 1; item->goalAnimState = STATE_GUIDE_STOP;
} }
else else
{ {
@ -361,33 +367,33 @@ void GuideControl(short itemNumber)
{ {
if (info.distance > 0x1000000) if (info.distance > 0x1000000)
{ {
item->goalAnimState = 3; item->goalAnimState = STATE_GUIDE_RUN;
} }
} }
else else
{ {
item->goalAnimState = 1; item->goalAnimState = STATE_GUIDE_STOP;
} }
} }
else if (Lara.location > item->itemFlags[3] && laraInfo.distance > 0x400000) else if (Lara.location > item->itemFlags[3] && laraInfo.distance > 0x400000)
{ {
item->goalAnimState = 3; item->goalAnimState = STATE_GUIDE_RUN;
} }
} }
else else
{ {
item->goalAnimState = 1; item->goalAnimState = STATE_GUIDE_STOP;
} }
} }
else else
{ {
item->goalAnimState = 1; item->goalAnimState = STATE_GUIDE_STOP;
} }
} }
break; break;
case 3: case STATE_GUIDE_RUN:
if (info.ahead) if (info.ahead)
{ {
joint2 = info.angle; joint2 = info.angle;
@ -398,7 +404,7 @@ void GuideControl(short itemNumber)
if (info.distance < SQUARE(2048) || Lara.location < item->itemFlags[3]) if (info.distance < SQUARE(2048) || Lara.location < item->itemFlags[3])
{ {
item->goalAnimState = 1; item->goalAnimState = STATE_GUIDE_STOP;
break; break;
} }
if (creature->reachedGoal) if (creature->reachedGoal)
@ -412,17 +418,17 @@ void GuideControl(short itemNumber)
break; break;
} }
item->goalAnimState = 1; item->goalAnimState = STATE_GUIDE_STOP;
} }
else if (foundEnemy && (info.distance < 0x200000 || !(item->swapMeshFlags & 0x40000) && info.distance < SQUARE(3072))) else if (foundEnemy && (info.distance < 0x200000 || !(item->swapMeshFlags & 0x40000) && info.distance < SQUARE(3072)))
{ {
item->goalAnimState = 1; item->goalAnimState = STATE_GUIDE_STOP;
break; break;
} }
break; break;
case 11: case STATE_GUIDE_IGNITE_TORCH:
// Ignite torch // Ignite torch
pos1.x = guideBiteInfo2.x; pos1.x = guideBiteInfo2.x;
pos1.y = guideBiteInfo2.y; pos1.y = guideBiteInfo2.y;
@ -715,7 +721,7 @@ void GuideControl(short itemNumber)
{ {
if (item->frameNumber == g_Level.Anims[item->animNumber].frameBase + 20) if (item->frameNumber == g_Level.Anims[item->animNumber].frameBase + 20)
{ {
item->goalAnimState = 1; item->goalAnimState = STATE_GUIDE_STOP;
floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &item->roomNumber); floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &item->roomNumber);
GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos); GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos);
@ -732,7 +738,7 @@ void GuideControl(short itemNumber)
if (item->frameNumber == g_Level.Anims[item->animNumber].frameBase + 70 && item->roomNumber == 70) if (item->frameNumber == g_Level.Anims[item->animNumber].frameBase + 70 && item->roomNumber == 70)
{ {
item->requiredAnimState = 3; item->requiredAnimState = STATE_GUIDE_RUN;
item->swapMeshFlags |= 0x200000; item->swapMeshFlags |= 0x200000;
SoundEffect(SFX_TR4_GUIDE_SCARE, &item->pos, 0); SoundEffect(SFX_TR4_GUIDE_SCARE, &item->pos, 0);
} }
@ -794,7 +800,7 @@ void GuideControl(short itemNumber)
} }
else if (item->triggerFlags <= 999) else if (item->triggerFlags <= 999)
{ {
item->goalAnimState = 1; item->goalAnimState = STATE_GUIDE_STOP;
} }
else else
{ {

View file

@ -38,7 +38,7 @@
#define ANIMATION_VON_CROY_STEP_DOWN_HIGH 36 #define ANIMATION_VON_CROY_STEP_DOWN_HIGH 36
#define ANIMATION_VON_CROY_CLIMB_UP_AFTER_JUMP 52 #define ANIMATION_VON_CROY_CLIMB_UP_AFTER_JUMP 52
#define SWAP_MESH_BITS_VON_CROY 0x40080 #define SWAPMESHFLAGS_VON_CROY 0x40080
#define VON_CROY_FLAG_JUMP 6 #define VON_CROY_FLAG_JUMP 6
@ -55,7 +55,7 @@ void InitialiseVonCroy(short itemNumber)
item->frameNumber = g_Level.Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = STATE_VON_CROY_TOGGLE_KNIFE; item->goalAnimState = STATE_VON_CROY_TOGGLE_KNIFE;
item->currentAnimState = STATE_VON_CROY_TOGGLE_KNIFE; item->currentAnimState = STATE_VON_CROY_TOGGLE_KNIFE;
item->swapMeshFlags = SWAP_MESH_BITS_VON_CROY; item->swapMeshFlags = SWAPMESHFLAGS_VON_CROY;
memset(VonCroyPassedWaypoints, 0, 128); memset(VonCroyPassedWaypoints, 0, 128);
} }
@ -106,6 +106,13 @@ void VonCroyControl(short itemNumber)
floor = GetFloor(x, item->pos.yPos, z, &roomNumber); floor = GetFloor(x, item->pos.yPos, z, &roomNumber);
int height3 = GetFloorHeight(floor, x, item->pos.yPos, z); int height3 = GetFloorHeight(floor, x, item->pos.yPos, z);
x += dx ;
z += dz ;
roomNumber = item->roomNumber;
floor = GetFloor(x, item->pos.yPos, z, &roomNumber);
int height4 = GetFloorHeight(floor, x, item->pos.yPos, z);
bool canJump1block; bool canJump1block;
if (item->boxNumber == LaraItem->boxNumber if (item->boxNumber == LaraItem->boxNumber
|| item->pos.yPos >= height1 - 384 || item->pos.yPos >= height1 - 384
@ -125,6 +132,17 @@ void VonCroyControl(short itemNumber)
else else
canJump2blocks = true; canJump2blocks = true;
bool canJump3blocks;
if (item->boxNumber == LaraItem->boxNumber
|| item->pos.yPos >= height1 - 384
|| item->pos.yPos >= height2 - 384
|| item->pos.yPos >= height3 - 384
|| item->pos.yPos >= height4 + 256
|| item->pos.yPos <= height4 - 256)
canJump3blocks = false;
else
canJump3blocks = true;
// Von Croy must follow Lara and navigate with ID_AI_FOLLOW objects // Von Croy must follow Lara and navigate with ID_AI_FOLLOW objects
item->aiBits = FOLLOW; item->aiBits = FOLLOW;
GetAITarget(creature); GetAITarget(creature);
@ -272,413 +290,125 @@ void VonCroyControl(short itemNumber)
short rot = 0; short rot = 0;
int dy, height, ceiling, flags; int dy, height, ceiling, flags;
printf("State: %d\n", item->currentAnimState);
switch (item->currentAnimState) switch (item->currentAnimState)
{ {
case STATE_VON_CROY_STOP: case STATE_VON_CROY_STOP:
creature->LOT.isMonkeying = false;
creature->LOT.isJumping = false; creature->LOT.isJumping = false;
joint2 = laraInfo.angle;
creature->flags = 0; creature->flags = 0;
creature->maximumTurn = 0; creature->maximumTurn = 0;
joint3 = info.angle / 2;
joint3 = 0; if (info.ahead && item->aiBits & FOLLOW)
joint2 = info.angle >> 1;
if (info.ahead)
{ {
joint1 = info.xAngle >> 1; joint1 = info.angle / 2;
joint0 = info.angle >> 1; joint2 = info.xAngle;
} }
if (item->requiredAnimState) if (item->aiBits & GUARD)
{ {
item->goalAnimState = item->requiredAnimState; joint3 = AIGuard(creature);
item->goalAnimState = 0;
break; break;
} }
/*if (item->itemFlags[2] == 2) if (item->aiBits & MODIFY)
{
rot = enemy->pos.yRot - item->pos.yRot;
if (rot < -1024)
{
item->goalAnimState = STATE_VON_CROY_LOOK_BACK_RIGHT;
break;
}
else if (rot > 1024)
{
item->goalAnimState = STATE_VON_CROY_LOOK_BACK_LEFT;
break;
}
else
{
item->itemFlags[2] = 0;
if (!item->flags)
{
creature->reachedGoal = false;
creature->enemy = NULL;
item->aiBits = FOLLOW;
item->location++;
break;
}
}
}*/
// Wait for Lara
if (Lara.location < item->location && creature->reachedGoal)
{ {
item->goalAnimState = STATE_VON_CROY_STOP; item->goalAnimState = STATE_VON_CROY_STOP;
if (item->floor > item->pos.yPos + (STEP_SIZE * 3))
item->aiBits &= ~MODIFY;
break; break;
} }
if (foundTarget != 0) if (canJump3blocks || item->itemFlags[2] == VON_CROY_FLAG_JUMP)
{ {
if (info.distance < SQUARE(3072) && (item->swapMeshFlags & SWAP_MESH_BITS_VON_CROY)) if (item->itemFlags[2] != VON_CROY_FLAG_JUMP && !canJump2blocks)
{ {
item->goalAnimState = STATE_VON_CROY_TOGGLE_KNIFE; item->goalAnimState = STATE_VON_CROY_JUMP_BACK;
break;
}
if (info.distance >= SQUARE(1024))
{
if (enemy != LaraItem && info.distance > SQUARE(640))
{
item->goalAnimState = STATE_VON_CROY_WALK;
break;
}
}
else if (!info.bite)
{
if (enemy->hitPoints > 0 && info.ahead)
{
if (abs(enemy->pos.yPos - item->pos.yPos + 512) < 512)
item->goalAnimState = STATE_VON_CROY_KNIFE_ATTACK_HIGH;
else
item->goalAnimState = STATE_VON_CROY_KNIFE_ATTACK_LOW;
}
}
break;
}
if (!creature->reachedGoal)
{
if (laraInfo.bite)
{
item->goalAnimState = STATE_VON_CROY_STOP;
break;
}
if (canJump1block || canJump2blocks)
{
creature->maximumTurn = 0;
item->animNumber = obj->animIndex + 22;
item->currentAnimState = STATE_VON_CROY_JUMP;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
if (canJump2blocks)
item->goalAnimState = STATE_VON_CROY_JUMP_2BLOCKS;
creature->LOT.isJumping = true;
break;
}
else if (creature->monkeyAhead)
{
floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
height = GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos);
if (GetCeiling(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos) == height - 1536)
{
/*if (!(item->swapMeshFlags & SWAP_MESH_BITS_VON_CROY))
{
item->goalAnimState = STATE_VON_CROY_TOGGLE_KNIFE;
break;
}
else
{*/
item->goalAnimState = STATE_VON_CROY_START_MONKEY;
break;
//}
}
}
else
{
if (foundTarget != 0)
{
if (info.distance < SQUARE(3072)
&& (item->swapMeshFlags & SWAP_MESH_BITS_VON_CROY))
{
item->goalAnimState = STATE_VON_CROY_TOGGLE_KNIFE;
break;
}
if (info.distance < SQUARE(1024))
{
if (!info.bite)
{
if (enemy->hitPoints > 0 && info.ahead)
{
if (abs(enemy->pos.yPos - item->pos.yPos + 512) < 512)
item->goalAnimState = STATE_VON_CROY_KNIFE_ATTACK_HIGH;
}
}
else
{
item->goalAnimState = STATE_VON_CROY_KNIFE_ATTACK_LOW;
}
break;
}
}
if ((info.distance < SQUARE(640)
|| laraInfo.distance > SQUARE(5120))
&& Lara.location < item->location)
break;
}
item->goalAnimState = STATE_VON_CROY_WALK;
break;
}
if (Lara.location <= item->location)
{
if (enemy && enemy->flags)
{
/*if (Lara.locationPad == item->location)
goto LAB_00419db3;*/
if (!enemy->flags && laraInfo.distance > 3072)
{
item->goalAnimState = STATE_VON_CROY_STOP;
break;
}
}
/*if (item->itemFlags[2] == 0)
{
if (laraInfo.angle < 1024)
{
if (laraInfo.angle < -1024)
{
item->goalAnimState = STATE_VON_CROY_LOOK_BACK_LEFT;
}
else
{
item->itemFlags[2] = 1;
}
}
else
{
item->goalAnimState = STATE_VON_CROY_LOOK_BACK_RIGHT;
}
break;
}*/
/*if (item->itemFlags[2] == 1)
{
if (!(GetRandomControl() & 0xF))
{
if (laraInfo.distance < SQUARE(3072))
item->goalAnimState = STATE_VON_CROY_CALL_LARA2;
else
item->goalAnimState = STATE_VON_CROY_CALL_LARA1;
}
else
{
item->itemFlags[2] = 0;
}
break;
}*/
creature->reachedGoal = false;
creature->enemy = NULL;
item->aiBits = FOLLOW;
item->location++;
break;
}
/*if (enemy->flags > 32)
{
if (enemy->flags == 34)
{
if (Lara.location <= item->location)
{
item->goalAnimState = 32;
break;
}
else
{
creature->reachedGoal = false;
creature->enemy = NULL;
item->aiBits = FOLLOW;
item->location += 2;
break;
}
}
else if (enemy->flags == 36)
{
if (Lara.location <= item->location)
{
item->goalAnimState = STATE_VON_CROY_STOP;
}
break;
}
else if (enemy->flags == 40)
{
if (item->itemFlags[2] != VON_CROY_FLAG_JUMP)
{
item->goalAnimState = STATE_VON_CROY_JUMP_BACK;
item->pos.xPos = enemy->pos.xPos;
item->pos.yPos = enemy->pos.yPos;
item->pos.zPos = enemy->pos.zPos;
item->pos.xRot = enemy->pos.xRot;
item->pos.yRot = enemy->pos.yRot;
item->pos.zRot = enemy->pos.zRot;
break;
}
else
{
item->goalAnimState = STATE_VON_CROY_RUN;
break;
}
}
else if (enemy->flags == 48)
{
GetFloorAndTestTriggers(
creature->aiTarget.pos.xPos,
creature->aiTarget.pos.yPos,
creature->aiTarget.pos.zPos,
creature->aiTarget.roomNumber,
1, 0);
creature->reachedGoal = false;
creature->enemy = NULL;
item->aiBits = FOLLOW;
item->location++;
break;
}
else if (enemy->flags == -1)
{
creature->reachedGoal = false;
creature->enemy = NULL;
item->aiBits = FOLLOW;
item->location++;
break;
} }
else else
{ {
break; item->goalAnimState = STATE_VON_CROY_RUN;
} }
}
if (enemy->flags == 2)
{
item->currentAnimState = STATE_VON_CROY_GRAB_LADDER;
item->animNumber = Objects[item->objectNumber].animIndex + 37;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->pos.xPos = enemy->pos.xPos;
item->pos.yPos = enemy->pos.yPos;
item->pos.zPos = enemy->pos.zPos;
item->pos.xRot = enemy->pos.xRot;
item->pos.yRot = enemy->pos.yRot;
item->pos.zRot = enemy->pos.zRot;
}
else if (enemy->flags == 4)
{
item->currentAnimState = STATE_VON_CROY_STEP_DOWN_HIGH;
item->animNumber = Objects[item->objectNumber].animIndex + 36;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->pos.xPos = enemy->pos.xPos;
item->pos.yPos = enemy->pos.yPos;
item->pos.zPos = enemy->pos.zPos;
item->pos.xRot = enemy->pos.xRot;
item->pos.yRot = enemy->pos.yRot;
item->pos.zRot = enemy->pos.zRot;
creature->LOT.isJumping = true;
}
else if (enemy->flags == 8)
{
item->goalAnimState = STATE_VON_CROY_ENABLE_TRAP;
break; break;
} }
else if (enemy->flags == 10) else if (canJump1block || canJump2blocks)
{
item->goalAnimState = STATE_VON_CROY_LOOK_BEFORE_JUMP;
break;
}
else if (enemy->flags == 12)
{ {
creature->maximumTurn = 0; creature->maximumTurn = 0;
item->animNumber = Objects[item->objectNumber].animIndex + 22; item->animNumber = Objects[item->objectNumber].animIndex + 22;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase; item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = STATE_VON_CROY_JUMP; item->currentAnimState = STATE_VON_CROY_JUMP;
if (canJump2blocks == 0) creature->LOT.isJumping = true;
{
if (!canJump2blocks && !canJump3blocks)
item->goalAnimState = STATE_VON_CROY_JUMP; item->goalAnimState = STATE_VON_CROY_JUMP;
}
else else
{ {
item->goalAnimState = STATE_VON_CROY_JUMP_2BLOCKS; item->goalAnimState = STATE_VON_CROY_JUMP_2BLOCKS;
} }
item->pos.xPos = enemy->pos.xPos;
item->pos.yPos = enemy->pos.yPos;
item->pos.zPos = enemy->pos.zPos;
item->pos.xRot = enemy->pos.xRot;
item->pos.yRot = enemy->pos.yRot;
item->pos.zRot = enemy->pos.zRot;
creature->LOT.isJumping = true;
}
else if (enemy->flags == 1 || enemy->flags == 3
|| enemy->flags == 5 || enemy->flags == 6
|| enemy->flags == 7 || enemy->flags == 9
|| enemy->flags == 11)
{
break; break;
} }
if (creature->monkeyAhead)
{
floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
height = GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos);
if (GetCeiling(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos) == height - 1536)
{
if (item->swapMeshFlags == SWAPMESHFLAGS_VON_CROY)
item->goalAnimState = STATE_VON_CROY_TOGGLE_KNIFE;
else
item->goalAnimState = STATE_VON_CROY_START_MONKEY;
break;
}
}
else else
{ {
GetFloorAndTestTriggers( if (creature->enemy && creature->enemy->hitPoints > 0 && info.distance < SQUARE(1024) && creature->enemy != LaraItem
creature->aiTarget.pos.xPos, && creature->enemy->objectNumber != ID_AI_FOLLOW)
creature->aiTarget.pos.yPos, {
creature->aiTarget.pos.zPos, if (info.bite)
creature->aiTarget.roomNumber, {
1, 0); if (enemy->hitPoints > 0 && info.ahead)
}*/ {
if (abs(enemy->pos.yPos - item->pos.yPos + 512) < 512)
item->goalAnimState = STATE_VON_CROY_KNIFE_ATTACK_HIGH;
else
item->goalAnimState = STATE_VON_CROY_KNIFE_ATTACK_LOW;
break;
}
}
}
}
creature->reachedGoal = false; item->goalAnimState = STATE_VON_CROY_WALK;
creature->enemy = NULL;
item->aiBits = FOLLOW;
item->location++;
break; break;
case STATE_VON_CROY_WALK: case STATE_VON_CROY_WALK:
creature->LOT.isJumping = false;
creature->LOT.isMonkeying = false; creature->LOT.isMonkeying = false;
creature->maximumTurn = ANGLE(6); creature->LOT.isJumping = false;
creature->maximumTurn = ANGLE(7);
creature->flags = 0;
if (laraInfo.ahead)
{
joint3 = laraInfo.angle;
}
else if (info.ahead)
{
joint3 = info.angle;
}
if (!laraInfo.ahead) if (canJump1block || canJump2blocks || canJump3blocks)
{
if (info.ahead)
{
joint2 = info.angle;
}
}
else
{
joint2 = laraInfo.angle;
}
if (item->requiredAnimState != 0)
{
item->goalAnimState = item->requiredAnimState;
break;
}
if ((Lara.location < item->location
&& laraInfo.distance >SQUARE(5120))
|| laraInfo.bite)
{ {
creature->maximumTurn = 0;
item->goalAnimState = STATE_VON_CROY_STOP; item->goalAnimState = STATE_VON_CROY_STOP;
break; break;
} }
if (creature->monkeyAhead) if (creature->reachedGoal && creature->monkeyAhead)
{ {
item->goalAnimState = STATE_VON_CROY_STOP; item->goalAnimState = STATE_VON_CROY_STOP;
break; break;
@ -686,65 +416,77 @@ void VonCroyControl(short itemNumber)
if (creature->reachedGoal) if (creature->reachedGoal)
{ {
if (enemy->flags != 32) if (!creature->enemy->flags)
{
creature->reachedGoal = false;
creature->enemy = NULL;
item->aiBits = FOLLOW;
item->itemFlags[3]++;
break;
}
item->goalAnimState = STATE_VON_CROY_STOP;
break;
}
else
{
if (Lara.location >= item->itemFlags[3])
{
if (!foundTarget || info.distance >= 0x200000 && (item->swapMeshFlags & 0x40000 || info.distance >= 9437184))
{
if (creature->enemy == LaraItem)
{
if (info.distance >= 0x400000)
{
if (info.distance > 0x1000000)
{
item->goalAnimState = STATE_VON_CROY_RUN;
}
}
else
{
item->goalAnimState = STATE_VON_CROY_STOP;
}
}
else if (Lara.location > item->itemFlags[3] && laraInfo.distance > 0x400000)
{
item->goalAnimState = STATE_VON_CROY_RUN;
}
}
else
{
item->goalAnimState = STATE_VON_CROY_STOP;
}
}
else
{
item->goalAnimState = STATE_VON_CROY_STOP;
}
}
if (info.bite)
{
if (info.distance < SQUARE(1024))
{ {
item->goalAnimState = STATE_VON_CROY_STOP; item->goalAnimState = STATE_VON_CROY_STOP;
break; break;
} }
else
{
GetFloorAndTestTriggers(
creature->aiTarget.pos.xPos,
creature->aiTarget.pos.yPos,
creature->aiTarget.pos.zPos,
creature->aiTarget.roomNumber,
1, 0);
creature->reachedGoal = false;
creature->enemy = NULL;
item->aiBits = FOLLOW;
item->location++;
break;
}
} }
if (foundTarget != NULL if (creature->mood == ATTACK_MOOD &&
&& (info.distance < SQUARE(1448) !(creature->jumpAhead) &&
|| ((item->swapMeshFlags & SWAP_MESH_BITS_VON_CROY) == 0 info.distance > SQUARE(1024))
&& (info.distance < SQUARE(3072)))))
{ {
item->goalAnimState = STATE_VON_CROY_STOP; item->goalAnimState = STATE_VON_CROY_RUN;
break;
} }
if (info.distance < SQUARE(640)
&& enemy->flags != 32)
{
item->goalAnimState = STATE_VON_CROY_STOP;
break;
}
if (info.distance < SQUARE(3072)
|| Lara.location < item->location)
break;
item->goalAnimState = STATE_VON_CROY_RUN;
break; break;
case STATE_VON_CROY_RUN: case STATE_VON_CROY_RUN:
if (info.ahead) if (info.ahead)
{ {
joint2 = info.angle; joint3 = info.angle;
} }
if (item->frameNumber == g_Level.Anims[item->animNumber].frameBase)
{
creature->LOT.isJumping = false;
creature->maximumTurn = ANGLE(8);
}
tilt = angle >> 1;
if (item->itemFlags[2] == VON_CROY_FLAG_JUMP) if (item->itemFlags[2] == VON_CROY_FLAG_JUMP)
{ {
creature->maximumTurn = 0; creature->maximumTurn = 0;
@ -752,56 +494,49 @@ void VonCroyControl(short itemNumber)
break; break;
} }
if (item->location <= Lara.location creature->maximumTurn = ANGLE(11);
&& !canJump1block == 0 tilt = abs(angle) / 2;
&& !laraInfo.bite)
if (info.distance < SQUARE(2048) || Lara.location < item->location)
{ {
if (creature->monkeyAhead) item->goalAnimState = STATE_VON_CROY_STOP;
{ break;
item->goalAnimState = STATE_VON_CROY_STOP; }
break;
}
if (!creature->reachedGoal) if (creature->reachedGoal)
{
if (!enemy->flags)
{ {
if (info.distance < SQUARE(640)
&& enemy->flags != 32
&& enemy->flags != 40)
{
item->goalAnimState = STATE_VON_CROY_STOP;
}
break;
}
if (enemy->flags == 32)
{
GetFloorAndTestTriggers(
creature->aiTarget.pos.xPos,
creature->aiTarget.pos.yPos,
creature->aiTarget.pos.zPos,
creature->aiTarget.roomNumber,
1, 0);
creature->reachedGoal = false; creature->reachedGoal = false;
creature->enemy = NULL; creature->enemy = NULL;
item->aiBits = FOLLOW; item->aiBits = FOLLOW;
item->location++; item->location;
break; break;
} }
if (info.distance < 512) item->goalAnimState = STATE_VON_CROY_STOP;
{ break;
if (enemy->flags == 40)
{
creature->maximumTurn = 0;
item->pos.yRot = enemy->pos.yRot;
item->goalAnimState = STATE_VON_CROY_JUMP_2BLOCKS;
item->itemFlags[2] = VON_CROY_FLAG_JUMP;
}
break;
}
} }
item->goalAnimState = STATE_VON_CROY_STOP; if (canJump1block
|| canJump2blocks
|| canJump3blocks
|| creature->monkeyAhead
|| item->aiBits & FOLLOW
|| info.distance < SQUARE(1024)
|| creature->jumpAhead)
{
item->goalAnimState = STATE_VON_CROY_STOP;
break;
}
if (info.distance < SQUARE(1024))
{
item->goalAnimState = STATE_VON_CROY_WALK;
break;
}
break; break;
case STATE_VON_CROY_START_MONKEY: case STATE_VON_CROY_START_MONKEY:
@ -839,13 +574,13 @@ void VonCroyControl(short itemNumber)
case STATE_VON_CROY_TOGGLE_KNIFE: case STATE_VON_CROY_TOGGLE_KNIFE:
if (item->frameNumber == g_Level.Anims[item->animNumber].frameBase) if (item->frameNumber == g_Level.Anims[item->animNumber].frameBase)
{ {
if (!(item->swapMeshFlags & SWAP_MESH_BITS_VON_CROY)) if (!(item->swapMeshFlags & SWAPMESHFLAGS_VON_CROY))
{ {
item->swapMeshFlags |= SWAP_MESH_BITS_VON_CROY; item->swapMeshFlags |= SWAPMESHFLAGS_VON_CROY;
} }
else else
{ {
item->swapMeshFlags &= ~SWAP_MESH_BITS_VON_CROY; item->swapMeshFlags &= ~SWAPMESHFLAGS_VON_CROY;
} }
} }
break; break;
@ -883,10 +618,12 @@ void VonCroyControl(short itemNumber)
|| item->frameNumber > g_Level.Anims[item->animNumber].frameBase + 5) || item->frameNumber > g_Level.Anims[item->animNumber].frameBase + 5)
{ {
creature->LOT.isJumping = true; creature->LOT.isJumping = true;
//if (canJump3blocks)
// item->itemFlags[2] = VON_CROY_FLAG_JUMP;
} }
else if (canJump1block) else if (canJump1block)
{ {
item->goalAnimState = STATE_VON_CROY_JUMP; item->goalAnimState = STATE_VON_CROY_JUMP;
} }
if (item->itemFlags[2] == VON_CROY_FLAG_JUMP) if (item->itemFlags[2] == VON_CROY_FLAG_JUMP)
@ -1098,7 +835,7 @@ void VonCroyControl(short itemNumber)
break; break;
case STATE_VON_CROY_JUMP_BACK: case STATE_VON_CROY_JUMP_BACK:
item->itemFlags[2] = 6; item->itemFlags[2] = VON_CROY_FLAG_JUMP;
break; break;
case 36: case 36:

View file

@ -733,7 +733,7 @@ static void StartBaddy(OBJECT_INFO* obj)
obj->savePosition = true; obj->savePosition = true;
obj->saveHitpoints = true; obj->saveHitpoints = true;
obj->saveMesh = true; obj->saveMesh = true;
obj->zoneType = ZONE_HUMAN_JUMP_AND_MONKEY; obj->zoneType = ZONE_HUMAN_LONGJUMP_AND_MONKEY;
g_Level.Bones[obj->boneIndex + 4 * 6] |= ROT_X; g_Level.Bones[obj->boneIndex + 4 * 6] |= ROT_X;
g_Level.Bones[obj->boneIndex + 4 * 6] |= ROT_Y; g_Level.Bones[obj->boneIndex + 4 * 6] |= ROT_Y;

View file

@ -2079,7 +2079,7 @@ namespace T5M::Renderer
printDebugMessage("Statics: %d", m_staticsToDraw.size()); printDebugMessage("Statics: %d", m_staticsToDraw.size());
printDebugMessage("Lights: %d", m_lightsToDraw.size()); printDebugMessage("Lights: %d", m_lightsToDraw.size());
printDebugMessage("Lara.roomNumber: %d", LaraItem->roomNumber); printDebugMessage("Lara.roomNumber: %d", LaraItem->roomNumber);
printDebugMessage("LaraItem.boxNumber: %d", LaraItem->boxNumber); printDebugMessage("LaraItem.boxNumber: %d, canJump: %d, canLongJump: %d, canMonkey: %d", LaraItem->boxNumber);
printDebugMessage("Lara.pos: %d %d %d", LaraItem->pos.xPos, LaraItem->pos.yPos, LaraItem->pos.zPos); printDebugMessage("Lara.pos: %d %d %d", LaraItem->pos.xPos, LaraItem->pos.yPos, LaraItem->pos.zPos);
printDebugMessage("Lara.rot: %d %d %d", LaraItem->pos.xRot, LaraItem->pos.yRot, LaraItem->pos.zRot); printDebugMessage("Lara.rot: %d %d %d", LaraItem->pos.xRot, LaraItem->pos.yRot, LaraItem->pos.zRot);
printDebugMessage("Lara.animNumber: %d", LaraItem->animNumber); printDebugMessage("Lara.animNumber: %d", LaraItem->animNumber);

View file

@ -962,15 +962,15 @@ void LoadBoxes()
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
// Ground zones // Ground zones
for (int j = 0; j < 4; j++) for (int j = 0; j < MAX_ZONES - 1; j++)
{ {
g_Level.Zones[j][i].resize(numBoxes * sizeof(int)); g_Level.Zones[j][i].resize(numBoxes * sizeof(int));
ReadBytes(g_Level.Zones[j][i].data(), numBoxes * sizeof(int)); ReadBytes(g_Level.Zones[j][i].data(), numBoxes * sizeof(int));
} }
// Fly zone // Fly zone
g_Level.Zones[4][i].resize(numBoxes * sizeof(int)); g_Level.Zones[MAX_ZONES - 1][i].resize(numBoxes * sizeof(int));
ReadBytes(g_Level.Zones[4][i].data(), numBoxes * sizeof(int)); ReadBytes(g_Level.Zones[MAX_ZONES - 1][i].data(), numBoxes * sizeof(int));
} }
// By default all blockable boxes are blocked // By default all blockable boxes are blocked

View file

@ -10,6 +10,8 @@
#define AddPtr(p, t, n) p = (t*)((char*)(p) + (ptrdiff_t)(n)); #define AddPtr(p, t, n) p = (t*)((char*)(p) + (ptrdiff_t)(n));
#define MESHES(slot, mesh) (Objects[slot].meshIndex + mesh) #define MESHES(slot, mesh) (Objects[slot].meshIndex + mesh)
#define MAX_ZONES 6
struct ChunkId; struct ChunkId;
struct LEB128; struct LEB128;
struct SAMPLE_INFO; struct SAMPLE_INFO;
@ -132,7 +134,7 @@ struct LEVEL
std::vector<SPRITE> Sprites; std::vector<SPRITE> Sprites;
std::vector<BOX_INFO> Boxes; std::vector<BOX_INFO> Boxes;
std::vector<OVERLAP> Overlaps; std::vector<OVERLAP> Overlaps;
std::vector<int> Zones[5][2]; std::vector<int> Zones[MAX_ZONES][2];
std::vector<short> SoundMap; std::vector<short> SoundMap;
std::vector<SAMPLE_INFO> SoundDetails; std::vector<SAMPLE_INFO> SoundDetails;
int NumItems; int NumItems;