From 97451f5cb6e5fee16aac33448e6bf7390faefee6 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Wed, 19 Sep 2018 20:48:17 +0200 Subject: [PATCH] Finished skeleton (needs fixing) --- Build/PCTomb5.idb | Bin 16422552 -> 16422552 bytes TR5Main/Game/control.h | 1 + TR5Main/Game/debris.h | 4 + TR5Main/Game/lot.cpp | 6 + TR5Main/Global/objectslist.h | 8 +- TR5Main/Global/types.h | 18 +++ TR5Main/Objects/animals.cpp | 283 ++++++++++++++++++++++++++++++++++- TR5Main/Objects/objects.h | 2 + TR5Main/Objects/skeleton.cpp | 171 +++++++++++++++++---- TR5Main/Specific/setup.cpp | 50 +++++++ 10 files changed, 507 insertions(+), 36 deletions(-) diff --git a/Build/PCTomb5.idb b/Build/PCTomb5.idb index bceb197b8d7d393c06e5214b6eaa3da0253a8fa8..a9bb969c874f4b612f07619f473164f904778559 100644 GIT binary patch delta 8443 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 V_`RJq@kcvr;?M1@iN7YB0sv$NZyEpq delta 6559 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 diff --git a/TR5Main/Game/control.h b/TR5Main/Game/control.h index aa5d9f10b..a2c13eac3 100644 --- a/TR5Main/Game/control.h +++ b/TR5Main/Game/control.h @@ -41,6 +41,7 @@ typedef enum GAME_STATUS { #define UpdateSpiders ((void (__cdecl*)()) 0x0047A340) #define UpdateShockwaves ((void (__cdecl*)()) 0x004849A0) #define UpdateLightning ((void (__cdecl*)()) 0x00484CB0) +#define ExplodeItemNode ((__int32 (__cdecl*)(ITEM_INFO*, __int32, __int32, __int32)) 0x0041ABF0) GAME_STATUS __cdecl DoTitle(__int32 index); GAME_STATUS __cdecl DoLevel(__int32 index, __int32 ambient, bool loadFromSavegame); diff --git a/TR5Main/Game/debris.h b/TR5Main/Game/debris.h index 50e96676b..2c94a34ca 100644 --- a/TR5Main/Game/debris.h +++ b/TR5Main/Game/debris.h @@ -1 +1,5 @@ #pragma once + +#include "..\Global\global.h" + +#define ShatterObject ((void (__cdecl*)(SHATTER_ITEM*, MESH_INFO*, __int16, __int16, __int32)) 0x0041D6B0) \ No newline at end of file diff --git a/TR5Main/Game/lot.cpp b/TR5Main/Game/lot.cpp index 4ff00b523..0246e7940 100644 --- a/TR5Main/Game/lot.cpp +++ b/TR5Main/Game/lot.cpp @@ -160,6 +160,12 @@ void __cdecl InitialiseSlot(__int16 itemNum, __int16 slot) creature->LOT.zone = 3; break; + case ID_SKELETON: + creature->LOT.step = 256; + creature->LOT.drop = -256; + creature->LOT.canJump = true; + break; + case ID_CROW: case ID_EAGLE: case ID_WILLOWISP: diff --git a/TR5Main/Global/objectslist.h b/TR5Main/Global/objectslist.h index 330e45d9e..e8162bba2 100644 --- a/TR5Main/Global/objectslist.h +++ b/TR5Main/Global/objectslist.h @@ -44,7 +44,7 @@ typedef enum object_types { ID_SKELETON, // TR4 - Working on ID_DOG, ID_CROCODILE, // TR4 - ID_LARA_EXTRA_ANIMS, // TR1-2-3 + ID_LARA_EXTRA_ANIMS, // TR1-2-3 - OK ID_MUMMY, // TR4 - OK ID_LARSON, ID_SMALL_SCORPION, // TR4 - OK @@ -158,7 +158,7 @@ typedef enum object_types { ID_TIGHT_ROPE, ID_PARALLEL_BARS, ID_XRAY_CONTROLLER, - ID_CUTSCENE_ROPE, + ID_RAT, // TR2 - OK ID_PORTAL, ID_GEN_SLOT1, ID_GEN_SLOT2, @@ -312,7 +312,7 @@ typedef enum object_types { ID_CLOSED_DOOR5, ID_RAPTOR, // TR3 - OK ID_CLOSED_DOOR6, - ID_TYRANNOSAUR, // TR3 - 287 + ID_TYRANNOSAUR, // TR3 - OK ID_LIFT_DOORS1, ID_COBRA, // TR3 - OK ID_LIFT_DOORS2, @@ -438,7 +438,7 @@ typedef enum object_types { ID_ANIMATING10, ID_BEAR, // TR1 - OK NEED TEST ID_ANIMATING11, - ID_GORILLA, // TR1 - 15 + ID_APE, // TR1 - OK NEED TEST ID_ANIMATING12, ID_WINGED_MUMMY, // TR1 - 20 ID_ANIMATING13, diff --git a/TR5Main/Global/types.h b/TR5Main/Global/types.h index 192305c08..49ac6e109 100644 --- a/TR5Main/Global/types.h +++ b/TR5Main/Global/types.h @@ -10,6 +10,14 @@ typedef struct vector_t __int32 pad; } VECTOR; +struct SPHERE +{ + long x; // size=0, offset=0 + long y; // size=0, offset=4 + long z; // size=0, offset=8 + long r; // size=0, offset=12 +}; + typedef struct svector_t { __int16 vx; @@ -1263,6 +1271,16 @@ typedef struct SPRITE float bottom; }; +struct SHATTER_ITEM +{ + SPHERE Sphere; // size=16, offset=0 + ITEM_LIGHT* il; // size=48, offset=16 + __int16* meshp; // size=0, offset=20 + __int32 bit; // size=0, offset=24 + __int16 yRot; // size=0, offset=28 + __int16 flags; // size=0, offset=30 +}; + typedef void (cdecl *EFFECT_ROUTINE)(ITEM_INFO*); typedef void (cdecl *LARA_COLLISION_ROUTINE)(ITEM_INFO*, COLL_INFO*); typedef void (cdecl *LARA_CONTROL_ROUTINE)(ITEM_INFO*, COLL_INFO*); diff --git a/TR5Main/Objects/animals.cpp b/TR5Main/Objects/animals.cpp index b81e9aa2b..fa6eacd17 100644 --- a/TR5Main/Objects/animals.cpp +++ b/TR5Main/Objects/animals.cpp @@ -21,6 +21,8 @@ BITE_INFO eagleBite = { 15, 46, 21, 6 }; BITE_INFO crowBite = { 2, 10, 60, 14 }; BITE_INFO wolfBite = { 0, -14, 174, 6 }; BITE_INFO bearBite = { 0, 96, 335, 14 }; +BITE_INFO apeBite = { 0, -19, 75, 15 }; +BITE_INFO mouseBite = { 0, 0, 57, 2 }; void __cdecl InitialiseWildBoar(__int16 itemNum) { @@ -1885,4 +1887,283 @@ void TyrannosaurControl(__int16 itemNum) CreatureAnimation(itemNum, angle, 0); item->collidable = true; -} \ No newline at end of file +} + +void __cdecl ApeControl(__int16 itemNum) +{ + if (!CreatureActive(itemNum)) + return; + + ITEM_INFO* item = &Items[itemNum]; + CREATURE_INFO* creature = (CREATURE_INFO*) item->data; + + __int16 head = 0; + __int16 angle = 0; + __int16 random = 0; + + if (item->hitPoints <= 0) + { + if (item->currentAnimState != 5) + { + item->animNumber = Objects[item->objectNumber].animIndex + 7 + (__int16)(GetRandomControl() / 0x4000); + item->frameNumber = Anims[item->animNumber].frameBase; + item->currentAnimState = 5; + } + } + else + { + AI_INFO info; + CreatureAIInfo(item, &info); + + if (info.ahead) + head = info.angle; + + GetCreatureMood(item, &info, TIMID); + CreatureMood(item, &info, TIMID); + + angle = CreatureTurn(item, creature->maximumTurn); + + if (item->hitStatus || info.distance < SQUARE(2048)) + creature->flags |= 1; + + switch (item->currentAnimState) + { + case 1: + 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; + } + + if (item->requiredAnimState) + item->goalAnimState = item->requiredAnimState; + else if (info.bite && info.distance < SQUARE(430)) + item->goalAnimState = 4; + else if (!(creature->flags & 1) && + info.zoneNumber == info.enemyZone && info.ahead) + { + random = (__int16)(GetRandomControl() >> 5); + if (random < 0xA0) + item->goalAnimState = 10; + else if (random < 0x140) + item->goalAnimState = 6; + else if (random < 0x1E0) + item->goalAnimState = 7; + else if (random < 0x2F0) + { + item->goalAnimState = 8; + creature->maximumTurn = 0; + } + else + { + item->goalAnimState = 9; + creature->maximumTurn = 0; + } + } + else + item->goalAnimState = 3; + break; + + case 3: + creature->maximumTurn = ANGLE(5); + + if (creature->flags == 0 && info.angle > -ANGLE(45) && info.angle < ANGLE(45)) + item->goalAnimState = 1; + else if (info.ahead && (item->touchBits & 0xFF00)) + { + item->requiredAnimState = 4; + item->goalAnimState = 1; + } + else if (creature->mood != MOOD_TYPE::ESCAPE_MOOD) + { + random = (__int16)GetRandomControl(); + if (random < 0xA0) + { + item->requiredAnimState = 10; + item->goalAnimState = 1; + } + else if (random < 0x140) + { + item->requiredAnimState = 6; + item->goalAnimState = 1; + } + else if (random < 0x1E0) + { + item->requiredAnimState = 7; + item->goalAnimState = 1; + } + } + break; + + case 8: + if (!(creature->flags & 4)) + { + item->pos.yRot -= ANGLE(90); + creature->flags |= 4; + } + + item->goalAnimState = 1; + break; + + case 9: + if (!(creature->flags & 2)) + { + item->pos.yRot += ANGLE(90); + creature->flags |= 2; + } + + item->goalAnimState = 1; + break; + + case 4: + if (!item->requiredAnimState && (item->touchBits & 0xFF00)) + { + CreatureEffect(item, &apeBite, DoBloodSplat); + + LaraItem->hitPoints -= 200; + LaraItem->hitStatus = true; + + item->requiredAnimState = 1; + } + break; + } + } + + CreatureJoint(item, 0, head); + + if (item->currentAnimState != 11) + { + 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; + } + + __int32 vault = CreatureVault(itemNum, angle, 2, 75); + + switch (vault) + { + case 2: + creature->maximumTurn = 0; + item->animNumber = Objects[item->objectNumber].animIndex + 19; + item->currentAnimState = 11; + item->frameNumber = Anims[item->animNumber].frameBase; + break; + + default: + return; + } + } + else + CreatureAnimation(itemNum, angle, 0); +} + +void __cdecl RatControl(__int16 itemNum) +{ + if (!CreatureActive(itemNum)) + return; + + ITEM_INFO* item = &Items[itemNum]; + CREATURE_INFO* creature = (CREATURE_INFO*) item->data; + + __int16 head = 0; + __int16 angle = 0; + __int16 random = 0; + + if (item->hitPoints <= 0) + { + if (item->currentAnimState != 6) + { + item->animNumber = Objects[item->objectNumber].animIndex + 9; + item->frameNumber = Anims[item->animNumber].frameBase; + item->currentAnimState = 6; + } + } + else + { + AI_INFO info; + CreatureAIInfo(item, &info); + + if (info.ahead) + head = info.angle; + + GetCreatureMood(item, &info, TIMID); + CreatureMood(item, &info, TIMID); + + angle = CreatureTurn(item, ANGLE(6)); + + switch (item->currentAnimState) + { + case 4: + if (creature->mood == MOOD_TYPE::BORED_MOOD || creature->mood == MOOD_TYPE::STALK_MOOD) + { + __int16 random = (__int16)GetRandomControl(); + if (random < 0x500) + item->requiredAnimState = 3; + else if (random > 0xA00) + item->requiredAnimState = 1; + } + else if (info.distance < SQUARE(340)) + item->requiredAnimState = 5; + else + item->requiredAnimState = 1; + + if (item->requiredAnimState) + item->goalAnimState = 2; + break; + + case 2: + creature->maximumTurn = 0; + + if (item->requiredAnimState) + item->goalAnimState = item->requiredAnimState; + break; + + case 1: + creature->maximumTurn = ANGLE(6); + + if (creature->mood == MOOD_TYPE::BORED_MOOD || creature->mood == MOOD_TYPE::STALK_MOOD) + { + random = (__int16)GetRandomControl(); + if (random < 0x500) + { + item->requiredAnimState = 3; + item->goalAnimState = 2; + } + else if (random < 0xA00) + item->goalAnimState = 2; + } + else if (info.ahead && info.distance < SQUARE(340)) + item->goalAnimState = 2; + break; + + case 5: + if (!item->requiredAnimState && (item->touchBits & 0x7F)) + { + CreatureEffect(item, &mouseBite, DoBloodSplat); + LaraItem->hitPoints -= 20; + LaraItem->hitStatus = true; + item->requiredAnimState = 2; + } + break; + + case 3: + if (GetRandomControl() < 0x500) + item->goalAnimState = 2; + break; + } + } + + CreatureJoint(item, 0, head); + CreatureAnimation(itemNum, angle, 0); +} diff --git a/TR5Main/Objects/objects.h b/TR5Main/Objects/objects.h index 42c7e5256..7e834e63b 100644 --- a/TR5Main/Objects/objects.h +++ b/TR5Main/Objects/objects.h @@ -8,6 +8,7 @@ void __cdecl ClampRotation(PHD_3DPOS *pos, __int16 angle, __int16 rot); void __cdecl InitialiseWolf(__int16 itemNum); void __cdecl WolfControl(__int16 itemNum); void __cdecl BearControl(__int16 itemNum); +void __cdecl ApeControl(__int16 itemNum); // TR2 objects void __cdecl BarracudaControl(__int16 itemNum); @@ -17,6 +18,7 @@ void __cdecl SpinningBlade(__int16 itemNum); void __cdecl InitialiseKillerStatue(__int16 itemNum); void __cdecl KillerStatueControl(__int16 itemNum); void __cdecl SpringBoardControl(__int16 itemNum); +void __cdecl RatControl(__int16 itemNum); // TR3 objects void __cdecl TigerControl(__int16 itemNum); diff --git a/TR5Main/Objects/skeleton.cpp b/TR5Main/Objects/skeleton.cpp index 87b93bbed..58dbc057e 100644 --- a/TR5Main/Objects/skeleton.cpp +++ b/TR5Main/Objects/skeleton.cpp @@ -9,6 +9,7 @@ #include "..\Game\sphere.h" #include "..\Game\effect2.h" #include "..\Game\people.h" +#include "..\Game\debris.h" BITE_INFO skeletonBite = { 0, -16, 200, 11 }; @@ -520,56 +521,164 @@ void __cdecl SkeletonControl(__int16 itemNum) { item->pos.yRot += info.angle; } - /*if (item->frameNumber > Anims[item->animNumber].frameBase + 15) + if (item->frameNumber > Anims[item->animNumber].frameBase + 15) { - v79 = Rooms + 148 * item->roomNumber; - v107 = 0; - v108 = 0; - v109 = 0; ROOM_INFO* room = &Rooms[item->roomNumber]; PHD_VECTOR pos; + GetJointAbsPosition(item, &pos, 16); - if ((*(*(v79 + 8) + 8 * (((v109 - *(v79 + 28)) >> 10) + *(v79 + 40) * ((v107 - *(v79 + 20)) >> 10)) + 2) & 0x8000) == 0x8000) + + FLOOR_INFO* floor = &room->floor[((z - room->z) >> 10) + room->ySize * ((x - room->x) >> 10)]; + if (floor->stopper) { - v80 = *(v79 + 16); - if (*(v79 + 50) > 0) + MESH_INFO* staticMesh = room->mesh; + if (room->numMeshes > 0) { - v105 = *(v79 + 50); - do + for (__int32 i = 0; i < room->numMeshes; i++) { - v81 = v109 ^ *(v80 + 8); - if (!(v81 & 0xFFFFFC00) && !((v107 ^ *v80) & 0xFFFFFC00) && *(v80 + 18) >= 50) + staticMesh = &room->mesh[i]; + if (abs(pos.x - staticMesh->x) < 1024 && abs(pos.z - staticMesh->z) < 1024 && staticMesh->staticNumber >= 50) { - LOWORD(v81) = LaraItem->roomNumber; - sub_432F00(0, v80, -64, v81, 0); - SoundEffect(347, pos, 0); - *(v80 + 16) &= 0xFEu; - v82 = *(v79 + 8); - v83 = ((v109 - *(v79 + 28)) >> 10) + *(v79 + 40) * ((v107 - *(v79 + 20)) >> 10); - *(v82 + 8 * v83 + 3) &= 0x7Fu; - GetHeight(v82 + 8 * v83, v107, v108, v109); + ShatterObject(0, staticMesh, -128, LaraItem->roomNumber, 0); + SoundEffect(347, &item->pos, 0); + staticMesh->Flags &= ~1; + floor->stopper = 0; + TrGetHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos); TestTriggers(TriggerIndex, 1, 0); } - v80 += 20; - --v105; - } while (v105); + } } } - if (!creature_1->flags) + if (!creature->flags) { if (item->touchBits & 0x18000) { LaraItem->hitPoints -= 80; - HIWORD(v84) = HIWORD(LaraItem); - LaraItem->MainFlags |= 0x10u; - LOWORD(v84) = item->pos.yRot; - CreatureEffect2(item, &unk_4AB2E8, 10, v84, DoBloodSplat); - SoundEffect(70, pos, 0); - creature_1->flags = 1; + LaraItem->hitStatus = true; + CreatureEffect2(item, &skeletonBite, 10, item->pos.yRot, DoBloodSplat); + SoundEffect(70, &item->pos, 0); + creature->flags = 1; } } - }*/ + } + break; + + case 7: + if (item->hitStatus) + { + if (item->meshBits == -1 && laraInfo.angle && Lara.gunType == WEAPON_SHOTGUN) + { + if (GetRandomControl() & 3) + { + item->goalAnimState = 17; + } + else + { + ExplodeItemNode(item, 11, 1, -24); + } + } + else + { + LABEL_153: + item->goalAnimState = 2; + } + } + else if (Lara.target != item || item->meshBits != -1 || Lara.gunType != WEAPON_SHOTGUN || !(GetRandomControl() & 0x7F)) + { + item->goalAnimState = 2; + } + break; + + case 21: + if (item->animNumber == Objects[item->objectNumber].animIndex + 43) + { + roomNumber = item->roomNumber; + floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber); + if (TrGetHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos) > item->pos.yPos + 1280) + { + creature->maximumTurn = 0; + item->animNumber = Objects[item->objectNumber].animIndex + 44; + item->frameNumber = Anims[item->animNumber].frameBase; + item->currentAnimState = 23; + creature->LOT.isJumping = false; + item->gravityStatus = true; + } + } + break; + + case 23: + case 24: + roomNumber = item->roomNumber; + floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber); + if (TrGetHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos) <= item->pos.yPos) + { + if (item->active) + { + ExplodingDeath(itemNum, -1, 929); + KillItem(itemNum); + DisableBaddieAI(itemNum); + //Savegame.Kills++; + } + } + break; + + case 25: + case 11: + case 12: + case 13: + if ((item->currentAnimState == 12 || item->currentAnimState == 13) && + item->frameNumber < Anims[item->animNumber].frameBase + 20) + { + item->hitPoints = 25; + creature->maximumTurn = 0; + break; + } + if (item->currentAnimState == 11) + { + creature->maximumTurn = 0; + break; + } + + item->hitPoints = 25; + creature->LOT.isJumping = false; + + roomNumber = item->roomNumber; + floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber); + if (TrGetHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos) <= item->pos.yPos + 1024) + { + if (!(GetRandomControl() & 0x1F)) + { + item->goalAnimState = 14; + } + } + else + { + creature->maximumTurn = 0; + item->animNumber = Objects[item->objectNumber].animIndex + 47; + item->frameNumber = Anims[item->animNumber].frameBase; + item->currentAnimState = 24; + item->gravityStatus = true; + } + break; + + case 19: + case 20: + creature->alerted = false; + creature->maximumTurn = 0; + item->status = ITEM_ACTIVE; + break; + + case 0: + if (item->frameNumber - Anims[item->animNumber].frameBase < 32) + { + //WakeUpSkeleton(item); + } + break; + + default: break; } + + CreatureAnimation(itemNum, angle, 0); } } \ No newline at end of file diff --git a/TR5Main/Specific/setup.cpp b/TR5Main/Specific/setup.cpp index 9779e3a59..af6ad0fe9 100644 --- a/TR5Main/Specific/setup.cpp +++ b/TR5Main/Specific/setup.cpp @@ -498,6 +498,56 @@ void __cdecl NewObjects() Bones[obj->boneIndex + 10 * 4] |= ROT_Y; Bones[obj->boneIndex + 11 * 4] |= ROT_Y; } + + obj = &Objects[ID_APE]; + if (obj->loaded) + { + obj->control = ApeControl; + obj->collision = CreatureCollision; + obj->hitPoints = 22; + obj->shadowSize = 128; + obj->pivotLength = 250; + obj->radius = 340; + obj->intelligent = true; + obj->savePosition = true; + obj->saveHitpoints = true; + obj->saveAnim = true; + obj->saveFlags = true; + } + + obj = &Objects[ID_RAT]; + if (obj->loaded) + { + obj->control = RatControl; + obj->collision = CreatureCollision; + obj->hitPoints = 5; + obj->shadowSize = 128; + obj->pivotLength = 50; + obj->radius = 204; + obj->intelligent = true; + obj->savePosition = true; + obj->saveHitpoints = true; + obj->saveAnim = true; + obj->saveFlags = true; + } + + obj = &Objects[ID_SKELETON]; + if (obj->loaded) + { + obj->initialise = InitialiseSkeleton; + obj->control = SkeletonControl; + obj->collision = CreatureCollision; + obj->hitPoints = 15; + obj->shadowSize = 128; + obj->pivotLength = 50; + obj->radius = 128; + obj->explodableMeshbits = 0xA00; + obj->intelligent = true; + obj->savePosition = true; + obj->saveHitpoints = true; + obj->saveAnim = true; + obj->saveFlags = true; + } } void __cdecl CustomObjects()