Skip to content

Commit

Permalink
fixed crash on hero party spawn limit
Browse files Browse the repository at this point in the history
  • Loading branch information
DiaLight committed Oct 20, 2024
1 parent a6848e1 commit 42e4137
Show file tree
Hide file tree
Showing 9 changed files with 817 additions and 299 deletions.
814 changes: 525 additions & 289 deletions mapping/DKII_EXE_v170.sgmap

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ add_executable(${TARGET}
dk2/CRoom.cpp
dk2/CBridge.cpp
dk2/CCamera.cpp
dk2/CWorld.cpp
dk2/button/button_types.cpp
dk2/button/CTextInput.cpp
dk2/entities/entities_type.cpp
Expand Down
14 changes: 7 additions & 7 deletions src/dk2/CRoom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,13 @@ int dk2::CRoom::tickWoodenBridge() {
++burnedCount;
mapElem->roomSetBurnLevel(0);
if (v8_unkIdx) {
CBridgeCmd v21_cmd;
v21_cmd.a1 = (pos.x << 12) + 2048;
v21_cmd.a2 = (pos.y << 12) + 2048;
v21_cmd.a3 = 0;
__int16 v14 = 0;
Pos2ub v19_bridgeLoc;
g_CWorld_ptr->v_sub_509580(v8_unkIdx, this->playerId, (int) &v21_cmd, (int) &v14, (int) &v19_bridgeLoc);
Vec3i pos2;
pos2.x = (pos.x << 12) + 2048;
pos2.y = (pos.y << 12) + 2048;
pos2.z = 0;
uint16_t v14_direction = 0;
CEffect *effect;
g_CWorld_ptr->v_sub_509580(v8_unkIdx, this->playerId, &pos2, &v14_direction, &effect);
}
if (burnedCount == 8) break;
}
Expand Down
273 changes: 273 additions & 0 deletions src/dk2/CWorld.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
//
// Created by DiaLight on 19.10.2024.
//
#include <dk2/CWorld.h>
#include <dk2/entities/CPlayer.h>
#include <dk2/entities/CActionPoint.h>
#include <dk2/entities/CCreature.h>
#include <dk2/entities/data/MyCreatureDataObj.h>
#include <dk2/world/map/MyMapElement.h>
#include "dk2_globals.h"
#include "dk2_functions.h"
#include "patches/micro_patches.h"


namespace dk2 {

void finalizeSpawnParty(CWorld *self, CPlayer *v57_player, uint8_t a2_heroPartyIdx, int v55_bool) {
unsigned __int16 f0_tagId = 0;
unsigned __int8 v46_positionInParty = 0;
CCreature *v68_leaderCreature = nullptr;
unsigned int v47_movementSpeed = 0x7FFFFFFF;
++self->invasionPartyCountArr[a2_heroPartyIdx];
CCreature *v53_creature_ = (CCreature *) sceneObjects[v57_player->ownedCreature_first];
for (CCreature *j = v53_creature_; j; j = (CCreature *) sceneObjects[j->fC_playerNodeY]) {
if (j->partyId != a2_heroPartyIdx) continue;
if (v47_movementSpeed > j->creatureData->speed_0)
v47_movementSpeed = j->creatureData->speed_0;
if ((j->flags & 2) != 0) { // LEADER
f0_tagId = j->f0_tagId;
v68_leaderCreature = j;
}
}
if (v55_bool) {
CCreature *v49_creature = (CCreature *) sceneObjects[f0_tagId];
Vec3i v65_pos;
v65_pos.x = v49_creature->f16_pos.x;
v65_pos.y = v49_creature->f16_pos.y;
v65_pos.z = 0x2000;
uint16_t v71_direction = 0;
CEffect *effect;
self->v_sub_509580(
43,
v49_creature->f24_playerId,
&v65_pos,
&v71_direction,
&effect);
}
CCreature *v53_creature = (CCreature *) sceneObjects[v57_player->ownedCreature_first];
for (CCreature *i = v53_creature; i; i = (CCreature *) sceneObjects[i->fC_playerNodeY]) {
if (i->partyId != a2_heroPartyIdx) continue;
i->setMovementSpeed(0, v47_movementSpeed);
if ((i->flags & 4) != 0) { // FOLLOWER
i->myLeadersId = f0_tagId;
i->positionInParty = ++v46_positionInParty;
}
}
if(hero_party_spawn_limit_fix::enabled) if(v68_leaderCreature == nullptr) return;
v68_leaderCreature->positionInParty = v46_positionInParty;
}

Vec3i findActionPointCenter(CWorld *self, int a3_actionPointId) {
unsigned __int16 fA_firstActionPointId = self->creatures.firstActionPointId;
for (CActionPoint *i = (CActionPoint *) sceneObjects[fA_firstActionPointId]; i;
i = (CActionPoint *) sceneObjects[i->f4_typeNodeY]) {
if(i->id != (BYTE) a3_actionPointId) continue;
uint16_t startY = i->start.y;
uint16_t endY = i->end.y;
uint16_t startX = i->start.x;
uint16_t endX = i->end.x;
Vec3i v65_vecCenter;
v65_vecCenter.z = 0;
v65_vecCenter.x = ((startX + endX) / 2) << 12;
v65_vecCenter.y = ((startY + endY) / 2) << 12;
return v65_vecCenter;
}
Vec3i v65_vecCenter;
memset(&v65_vecCenter, 0, sizeof(v65_vecCenter));
return v65_vecCenter;
}
MyCreatureDataObj *findCreatureDataObjForParty(
CWorld *self, bool a4_bool, unsigned int v23_goodIdx,
int v59_creatureDataArrCount, GoodCreature &v68_goodCr,
char &f1C_creatureTypeId) {
if (!a4_bool) {
f1C_creatureTypeId = v68_goodCr.creatureTypeId;
return self->v_fun_50D390(v68_goodCr.creatureTypeId);
}
if (!v23_goodIdx) {
f1C_creatureTypeId = 14; // Dwarf
return self->v_fun_50D390(14u);
}
while(true) {
char v27_randomType = randomInt(
v59_creatureDataArrCount,
&self->gameSeed,
(char *) "D:\\Dev\\DK2\\Projects\\Source\\Game\\WorldTrigger.cpp",
1586
);
f1C_creatureTypeId = v27_randomType + 1;
MyCreatureDataObj *v30_creatureDataObj = self->v_fun_50D390(f1C_creatureTypeId);
if(!v30_creatureDataObj) continue;
if((v30_creatureDataObj->flags & 0x40000000) == 0) continue;
return v30_creatureDataObj;
}
}

int spawnWholeParty(CWorld *self, uint8_t a2_heroPartyIdx, int a3_actionPointId, bool a4_bool) {
CPlayer *fA_players_7 = self->playerList.players_7;
CPlayer *v57_player = fA_players_7;
GoodCreature v68_goodCr;
int v55_bool = 1;
Vec3i v65_vecCenter = findActionPointCenter(self, a3_actionPointId);
MyMapElement *v12_mapelem = self->v_getMapElem_2(&v65_vecCenter);
unsigned __int8 fA_arr6DA4A8_idx = v12_mapelem->arr6DA4A8_idx;
if (fA_arr6DA4A8_idx == 33) {
v65_vecCenter.y += 4096;
v65_vecCenter.x += 4096;
uint16_t v69_direction = 0;
CEffect *v61_effect;
self->v_sub_509580(
311,
g_goodPlayerId,
&v65_vecCenter,
&v69_direction,
&v61_effect);
v55_bool = 0;
} else if (fA_arr6DA4A8_idx == 37) {
v55_bool = 0;
}
for (CCreature *i_creature = (CCreature *) sceneObjects[v12_mapelem->sceneObjIdx];
i_creature;
i_creature = (CCreature *) sceneObjects[i_creature->f8_mapWhoNodeY]) {
int fE_type = i_creature->fE_type;
if (fE_type == 4 || fE_type == 3) {
i_creature->v_f20();
uint16_t v69_direction = 0;
CEffect *v61_effect;
self->v_sub_509580(1, i_creature->f24_playerId, &v65_vecCenter, &v69_direction, &v61_effect);
}
}

__int16 v21_triggerId = self->_heroPartyArr[a2_heroPartyIdx].triggerId;
if (v21_triggerId) self->_set_trigger_flag_sub_519A20(v21_triggerId, 1);
int v22_creatureDataArrCount = self->v_loc_508E50();
unsigned int v23_goodIdx = 0;
while (true) {
v68_goodCr = self->_heroPartyArr[a2_heroPartyIdx].goodCreatures[v23_goodIdx];
if (v68_goodCr.creatureTypeId) {
CCreature *v53_creature;
char f1C_creatureTypeId;
MyCreatureDataObj *v30_creatureDataObj = findCreatureDataObjForParty(
self, a4_bool, v23_goodIdx, v22_creatureDataArrCount, v68_goodCr,
f1C_creatureTypeId);
if (!self->WorldTrigger_spawnCreatureByTrigger(
v57_player->f0_tagId,
f1C_creatureTypeId,
&v65_vecCenter,
&v53_creature)) {
if(hero_party_spawn_limit_fix::enabled) {
finalizeSpawnParty(self, v57_player, a2_heroPartyIdx, v55_bool);
return 1;
}
return 0;
}
if (f1C_creatureTypeId == 21) { // King
for (CPlayer *j_player = (CPlayer *) sceneObjects[self->playerList.allocatedList];
j_player;
j_player = (CPlayer *) sceneObjects[j_player->nextIdx]) {
self->playerMessageQueue.fun_4C4600(
5, j_player->f0_tagId,
1, v53_creature->f0_tagId, 1);
}
}
unsigned __int8 fE_level = v68_goodCr.level;
BYTE v69_count = v68_goodCr.level - 1;
if (a4_bool) {
unsigned __int8 InvasionPartyCount = self->getInvasionPartyCount(a2_heroPartyIdx);
v69_count = InvasionPartyCount + (BYTE) v69_count;
}
v69_count %= 10;

unsigned int v36_maxGoldHeld;
if (fE_level == 1) {
v36_maxGoldHeld = v30_creatureDataObj->_maxGoldHeld;
} else {
v36_maxGoldHeld = v30_creatureDataObj->_maxGoldHeld
* g_pObj6F2550->_maxGoldHeldMultiplier_byLevel[fE_level]
/ 100;
}
v53_creature->fun_48AE70((__int64) ((double) v68_goodCr.goldHeldPercent * 0.01 * (double) v36_maxGoldHeld));

int f692_health;
if (fE_level == 1) {
f692_health = v30_creatureDataObj->health;
} else {
f692_health = v30_creatureDataObj->health * g_pObj6F2550->healthMultiplier_byLevel[fE_level] / 100;
}
v53_creature->processTakeDamage(
(__int64) ((double) v68_goodCr.initialHealth * 0.01 * (double) (unsigned int) f692_health)
- v53_creature->f3C_health,
g_goodPlayerId,
0);

int v38_count = v69_count;
if ((BYTE) v69_count) {
int v39_count = (unsigned __int8) v69_count;
do {
v53_creature->fun_48B120();
--v39_count;
} while (v39_count);
}
unsigned __int8 f1D_wanderRadius = v68_goodCr.wanderRadius;
v53_creature->field_34 = 0;
v53_creature->wanderRadius = f1D_wanderRadius;
unsigned __int16 v41_goodAttackPlayerId = 0;
v53_creature->partyId = v68_goodCr.partyId;
if (v68_goodCr.objectiveTargetPlayerId)
v41_goodAttackPlayerId = self->playerList.players_7[v68_goodCr.objectiveTargetPlayerId - 1].f0_tagId;
if (!a4_bool || v38_count) {
v53_creature->setGoodJob(
v68_goodCr.objective_goodJob,
v41_goodAttackPlayerId,
v68_goodCr.objectiveTargetActionPointId);
} else {
v53_creature->setGoodJob(19, v41_goodAttackPlayerId, v68_goodCr.objectiveTargetActionPointId);
}
unsigned int fF_behaviourFlags = v68_goodCr.behaviourFlags;
v53_creature->setWillFight(v68_goodCr.behaviourFlags & 1);
v53_creature->setLeader((fF_behaviourFlags >> 1) & 1);
v53_creature->setFollower((fF_behaviourFlags >> 2) & 1);
v53_creature->setWillBeAttacked((fF_behaviourFlags >> 3) & 1);
v53_creature->setActAsDropped((fF_behaviourFlags >> 6) & 1);
v53_creature->setStartAsDying(fF_behaviourFlags >> 7);
v53_creature->setFreeFriendsOnJaiBreak((fF_behaviourFlags >> 5) & 1);
unsigned int f1F_behaviourFlags2 = v68_goodCr.behaviourFlags2;
v53_creature->setDestroyRooms(v68_goodCr.behaviourFlags2 & 1);
v53_creature->setIAmaTool((f1F_behaviourFlags2 & 2) != 0);
v53_creature->setIAmAMercenary((f1F_behaviourFlags2 >> 3) & 1);
v53_creature->setDiesInstantly((f1F_behaviourFlags2 & 4) != 0);
__int16 f18_triggerId = v68_goodCr.triggerId;
v53_creature->setTriggerId(v68_goodCr.triggerId);
if (f18_triggerId) {
self->_set_trigger_flag_sub_519A20(f18_triggerId, 1);
}
v53_creature->fun_49AA30(3, 0, 0);
if (v55_bool) {
v53_creature->setCurrentState_48AD30(269);
v53_creature->renderInfo.fAF &= ~1u;
}
}
++v23_goodIdx;
if (v23_goodIdx >= 0x10) {
finalizeSpawnParty(self, v57_player, a2_heroPartyIdx, v55_bool);
return 1;
}
}
}

}


int dk2::CWorld::WorldTrigger_cpp_519F90(__int16 a2_heroPartyIdx, int a3_actionPointId, int a4_bool) {
if (!(BYTE) a4_bool) return spawnWholeParty(this, a2_heroPartyIdx, a3_actionPointId, (BYTE) a4_bool);
CPlayer *fA_players_7 = this->playerList.players_7;
CCreature *v6_creature = (CCreature *) sceneObjects[fA_players_7->ownedCreature_first];
for (CCreature *i = v6_creature; i; v6_creature = (CCreature *) sceneObjects[v6_creature->fC_playerNodeY]) {
if(v6_creature->partyId == (uint8_t) a2_heroPartyIdx
&& (v6_creature->prisonOwner == 0)
&& (v6_creature->stateFlags & 0x200000) == 0 // creatureDying
) return 1;
}
return spawnWholeParty(this, (uint8_t) a2_heroPartyIdx, a3_actionPointId, (BYTE) a4_bool);
}
4 changes: 2 additions & 2 deletions src/dk2/MyComputerPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ namespace dk2 {
updateFlags_success(cp);
return;
}
CTag *v68_creature = sceneObjects[fE_cplayer->thingsOwnedList[0]];
CTag *v68_creature = sceneObjects[fE_cplayer->ownedCreature_first];
CCreature *v20_creature = (CCreature *) v68_creature;
if (v68_creature) {
do {
Expand Down Expand Up @@ -252,7 +252,7 @@ namespace dk2 {
return;
}
CCreature *i_creature;
for (i_creature = (CCreature *) sceneObjects[cp->cplayer->thingsOwnedList[0]];
for (i_creature = (CCreature *) sceneObjects[cp->cplayer->ownedCreature_first];
i_creature;
i_creature = (CCreature *) sceneObjects[i_creature->fC_playerNodeY]) {
int v5_respondIdx = (cp->flags >> 14) & 0xF;
Expand Down
2 changes: 1 addition & 1 deletion src/dk2/entities/CPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ int dk2::CPlayer::creatureDidWorkshopWork(int workMade, CCreature *a3_creature)
}

void dk2::CPlayer::resetCreaturesState() {
for (CCreature *creature = (CCreature *) sceneObjects[this->thingsOwnedList[0]];
for (CCreature *creature = (CCreature *) sceneObjects[this->ownedCreature_first];
creature;
creature = (CCreature *) sceneObjects[creature->fC_playerNodeY]) {
int curStateId = creature->cstate.currentStateId;
Expand Down
1 change: 1 addition & 0 deletions src/patches/micro_patches.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ bool wooden_bridge_burn_fix::enabled = true;
bool max_host_port_number_fix::enabled = true;
bool increase_zoom_level::enabled = true;
bool fix_chat_buffer_invalid_memory_access::enabled = true;
bool hero_party_spawn_limit_fix::enabled = true;

bool override_max_room_count::enabled = true;
uint8_t override_max_room_count::limit = 255; // default is 96
Expand Down
4 changes: 4 additions & 0 deletions src/patches/micro_patches.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ namespace fix_chat_buffer_invalid_memory_access {
extern bool enabled;
}

namespace hero_party_spawn_limit_fix {
extern bool enabled;
}

namespace override_max_room_count {
extern bool enabled;
extern uint8_t limit;
Expand Down
3 changes: 3 additions & 0 deletions src/replace_globals.map
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,6 @@
# CCamera.h
00449CA0 void zoomRel_449CA0(int); // --------------- /* auto */

# CWorld.h
00519F90 int WorldTrigger_cpp_519F90(int16_t, int, int); /* auto */

0 comments on commit 42e4137

Please sign in to comment.