diff options
| author | fusion32 <marcopuzziello@gmail.com> | 2025-06-07 23:52:37 -0300 |
|---|---|---|
| committer | fusion32 <marcopuzziello@gmail.com> | 2025-06-07 23:52:37 -0300 |
| commit | 0590a5f1b3e0ffe295d7894a16b9d8aff3fae586 (patch) | |
| tree | 6a340a2d415185f3634c2206e00e630bea998474 | |
| parent | 3d7fcfc4a6a1fc7016145b39596775bcd32be5c1 (diff) | |
| download | game-0590a5f1b3e0ffe295d7894a16b9d8aff3fae586.tar.gz game-0590a5f1b3e0ffe295d7894a16b9d8aff3fae586.zip | |
implement monster raids
| -rw-r--r-- | TODO.md | 6 | ||||
| -rw-r--r-- | reference/game.c | 974 | ||||
| -rw-r--r-- | reference/types.hh | 15 | ||||
| -rw-r--r-- | src/containers.hh | 22 | ||||
| -rw-r--r-- | src/cr.hh | 32 | ||||
| -rw-r--r-- | src/crmain.cc | 420 | ||||
| -rw-r--r-- | src/objects.cc | 2 | ||||
| -rw-r--r-- | src/stubs.hh | 4 |
8 files changed, 463 insertions, 1012 deletions
@@ -1,11 +1,5 @@ ## TODO NEXT - CRACT.CC -- CRMAIN.CC - - TCreature::CreatureMoveStimulus - - FINDCREATURES - - KILL STATS - - RACE - - RAIDS - CRPLAYER.CC, CRNONPL.CC - HOUSES.CC - INFO.CC diff --git a/reference/game.c b/reference/game.c index f0a4f51..0a5a2e5 100644 --- a/reference/game.c +++ b/reference/game.c @@ -29623,980 +29623,6 @@ void __static_initialization_and_destruction_0(int __initialize_p,int __priority return;
}
-// DWARF original prototype: void TAttackWave(TAttackWave * this)
-
-void __thiscall TAttackWave::TAttackWave(TAttackWave *this)
-
-{
- vector<TItemData>::vector(&this->ExtraItem,1,5,5);
- this->x = 0;
- this->y = 0;
- this->z = 0;
- this->Spread = 0;
- this->Race = -1;
- this->MinCount = 0;
- this->MaxCount = 0;
- this->Radius = 0x7fffffff;
- this->Lifetime = 0;
- this->Message = 0;
- this->ExtraItems = 0;
- return;
-}
-
-
-
-// DWARF original prototype: void TAttackWave(TAttackWave * this)
-
-void __thiscall TAttackWave::TAttackWave(TAttackWave *this)
-
-{
- vector<TItemData>::vector(&this->ExtraItem,1,5,5);
- this->x = 0;
- this->y = 0;
- this->z = 0;
- this->Spread = 0;
- this->Race = -1;
- this->MinCount = 0;
- this->MaxCount = 0;
- this->Radius = 0x7fffffff;
- this->Lifetime = 0;
- this->Message = 0;
- this->ExtraItems = 0;
- return;
-}
-
-
-
-// DWARF original prototype: void ~TAttackWave(TAttackWave * this, int __in_chrg)
-
-void __thiscall TAttackWave::~TAttackWave(TAttackWave *this,int __in_chrg)
-
-{
- TItemData *pTVar1;
-
- if (this->Message != 0) {
- DeleteDynamicString(this->Message);
- }
- pTVar1 = (this->ExtraItem).entry;
- if (pTVar1 == (TItemData *)0x0) {
- return;
- }
- operator_delete__(pTVar1);
- return;
-}
-
-
-
-// DWARF original prototype: void ~TAttackWave(TAttackWave * this, int __in_chrg)
-
-void __thiscall TAttackWave::~TAttackWave(TAttackWave *this,int __in_chrg)
-
-{
- TItemData *pTVar1;
-
- if (this->Message != 0) {
- DeleteDynamicString(this->Message);
- }
- pTVar1 = (this->ExtraItem).entry;
- if (pTVar1 == (TItemData *)0x0) {
- return;
- }
- operator_delete__(pTVar1);
- return;
-}
-
-
-
-void LoadMonsterRaid(char *FileName,int Start,bool *Type,int *Date,int *Interval,int *Duration)
-
-{
- TReadScriptFile *pTVar1;
- bool bVar2;
- char cVar3;
- char *pcVar4;
- char *pcVar5;
- TAttackWave *this;
- TItemData *this_00;
- ulong uVar6;
- undefined4 *puVar7;
- int End;
- int iVar8;
- int iVar9;
- char *pcVar10;
- undefined1 uVar11;
- char *in_stack_ffffbfac;
- int Delay;
- TAttackWave *AttackWave;
- ObjectType local_402c [4];
- char local_401c [4];
- char Ident [30];
- TReadScriptFile Script;
-
- if (FileName == (char *)0x0) {
- pcVar4 = "LoadMonsterRaid: Dateiname ist NULL.\n";
-LAB_080a45c3:
- // try { // try from 080a45c3 to 080a45f1 has its CatchHandler @ 080a4636
- error(pcVar4);
- puVar7 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar7 = "cannot load monster raid";
- // WARNING: Subroutine does not return
- __cxa_throw(puVar7,char_const*::typeinfo,0);
- }
- uVar11 = Start == 0;
- if (Start < 0) {
- if ((((Type == (bool *)0x0) || (Date == (int *)0x0)) || (Interval == (int *)0x0)) ||
- (uVar11 = Duration == (int *)0x0, (bool)uVar11)) {
- pcVar4 = &DAT_08102420;
- goto LAB_080a45c3;
- }
- *Date = 0;
- *Interval = 0;
- *Duration = 0;
- }
- else {
- in_stack_ffffbfac = FileName;
- // try { // try from 080a3d82 to 080a3d94 has its CatchHandler @ 080a4636
- print();
- }
- TReadScriptFile::TReadScriptFile((TReadScriptFile *)(Ident + 0x1c));
- pTVar1 = (TReadScriptFile *)(Ident + 0x1c);
- // try { // try from 080a3da2 to 080a3ebd has its CatchHandler @ 080a4630
- TReadScriptFile::open(pTVar1,FileName,(int)in_stack_ffffbfac);
- TReadScriptFile::nextToken(pTVar1);
- pcVar4 = TReadScriptFile::getIdentifier(pTVar1);
- iVar8 = 0xc;
- pcVar5 = "description";
- do {
- if (iVar8 == 0) break;
- iVar8 = iVar8 + -1;
- uVar11 = *pcVar4 == *pcVar5;
- pcVar4 = pcVar4 + 1;
- pcVar5 = pcVar5 + 1;
- } while ((bool)uVar11);
- if ((bool)uVar11) {
- TReadScriptFile::readSymbol((TReadScriptFile *)(Ident + 0x1c),'=');
- TReadScriptFile::readString((TReadScriptFile *)(Ident + 0x1c));
- TReadScriptFile::nextToken((TReadScriptFile *)(Ident + 0x1c));
- }
- pcVar4 = TReadScriptFile::getIdentifier((TReadScriptFile *)(Ident + 0x1c));
- iVar8 = 5;
- pcVar5 = "type";
- do {
- if (iVar8 == 0) break;
- iVar8 = iVar8 + -1;
- uVar11 = *pcVar4 == *pcVar5;
- pcVar4 = pcVar4 + 1;
- pcVar5 = pcVar5 + 1;
- } while ((bool)uVar11);
- if (!(bool)uVar11) {
- TReadScriptFile::error((TReadScriptFile *)(Ident + 0x1c),"type expected");
- }
- TReadScriptFile::readSymbol((TReadScriptFile *)(Ident + 0x1c),'=');
- TReadScriptFile::readIdentifier((TReadScriptFile *)(Ident + 0x1c));
- uVar11 = Start == 0;
- if (Start < 0) {
- pcVar4 = TReadScriptFile::getIdentifier((TReadScriptFile *)(Ident + 0x1c));
- iVar8 = 8;
- pcVar5 = "bigraid";
- do {
- if (iVar8 == 0) break;
- iVar8 = iVar8 + -1;
- uVar11 = *pcVar4 == *pcVar5;
- pcVar4 = pcVar4 + 1;
- pcVar5 = pcVar5 + 1;
- } while ((bool)uVar11);
- *Type = (bool)uVar11;
- }
- TReadScriptFile::readIdentifier((TReadScriptFile *)(Ident + 0x1c));
- pcVar4 = TReadScriptFile::getIdentifier((TReadScriptFile *)(Ident + 0x1c));
- iVar8 = 5;
- pcVar5 = "date";
- do {
- if (iVar8 == 0) break;
- iVar8 = iVar8 + -1;
- uVar11 = *pcVar4 == *pcVar5;
- pcVar4 = pcVar4 + 1;
- pcVar5 = pcVar5 + 1;
- } while ((bool)uVar11);
- if ((bool)uVar11) {
- pcVar4 = (char *)0x3d;
- TReadScriptFile::readSymbol((TReadScriptFile *)(Ident + 0x1c),'=');
- TReadScriptFile::readNumber((TReadScriptFile *)(Ident + 0x1c));
- uVar11 = Start == 0;
- if (-1 < Start) goto LAB_080a3e84;
- iVar8 = TReadScriptFile::getNumber((TReadScriptFile *)(Ident + 0x1c));
- }
- else {
- pcVar4 = TReadScriptFile::getIdentifier((TReadScriptFile *)(Ident + 0x1c));
- iVar8 = 9;
- pcVar5 = "interval";
- do {
- if (iVar8 == 0) break;
- iVar8 = iVar8 + -1;
- uVar11 = *pcVar4 == *pcVar5;
- pcVar4 = pcVar4 + 1;
- pcVar5 = pcVar5 + 1;
- } while ((bool)uVar11);
- if (!(bool)uVar11) {
- pcVar4 = "date or interval expected";
- TReadScriptFile::error((TReadScriptFile *)(Ident + 0x1c),"date or interval expected");
- goto LAB_080a3e84;
- }
- pcVar4 = (char *)0x3d;
- TReadScriptFile::readSymbol((TReadScriptFile *)(Ident + 0x1c),'=');
- TReadScriptFile::readNumber((TReadScriptFile *)(Ident + 0x1c));
- uVar11 = Start == 0;
- if (-1 < Start) goto LAB_080a3e84;
- iVar8 = TReadScriptFile::getNumber((TReadScriptFile *)(Ident + 0x1c));
- Date = Interval;
- }
- *Date = iVar8;
-LAB_080a3e84:
- pcVar5 = TReadScriptFile::readIdentifier((TReadScriptFile *)(Ident + 0x1c));
- iVar8 = 6;
- pcVar10 = "delay";
- do {
- if (iVar8 == 0) break;
- iVar8 = iVar8 + -1;
- uVar11 = *pcVar5 == *pcVar10;
- pcVar5 = pcVar5 + 1;
- pcVar10 = pcVar10 + 1;
- } while ((bool)uVar11);
- if (!(bool)uVar11) {
- pcVar4 = "delay expected";
- TReadScriptFile::error((TReadScriptFile *)(Ident + 0x1c),"delay expected");
- }
- do {
- if (unique0x100007f5 != 1) {
- TReadScriptFile::close((TReadScriptFile *)(Ident + 0x1c),(int)pcVar4);
- // try { // try from 080a3ec7 to 080a3ecb has its CatchHandler @ 080a4636
- TReadScriptFile::~TReadScriptFile((TReadScriptFile *)(Ident + 0x1c),(int)pcVar4);
- return;
- }
- pcVar4 = (char *)0x3d;
- // try { // try from 080a3eea to 080a3f08 has its CatchHandler @ 080a4630
- TReadScriptFile::readSymbol((TReadScriptFile *)(Ident + 0x1c),'=');
- iVar8 = TReadScriptFile::readNumber((TReadScriptFile *)(Ident + 0x1c));
- this = (TAttackWave *)operator_new(0x54);
- // try { // try from 080a3f0e to 080a3f12 has its CatchHandler @ 080a45fb
- TAttackWave::TAttackWave(this);
- // try { // try from 080a3f22 to 080a4573 has its CatchHandler @ 080a4630
- while (TReadScriptFile::nextToken((TReadScriptFile *)(Ident + 0x1c)), stack0xffffc004 != 0)
- {
- uVar11 = stack0xffffc004 == 1;
- if (!(bool)uVar11) {
- pcVar4 = "identifier expected";
- TReadScriptFile::error((TReadScriptFile *)(Ident + 0x1c),"identifier expected");
- }
- pcVar5 = TReadScriptFile::getIdentifier((TReadScriptFile *)(Ident + 0x1c));
- iVar9 = 6;
- pcVar10 = "delay";
- do {
- if (iVar9 == 0) break;
- iVar9 = iVar9 + -1;
- uVar11 = *pcVar5 == *pcVar10;
- pcVar5 = pcVar5 + 1;
- pcVar10 = pcVar10 + 1;
- } while ((bool)uVar11);
- if ((bool)uVar11) break;
- pcVar4 = TReadScriptFile::getIdentifier((TReadScriptFile *)(Ident + 0x1c));
- strcpy(local_401c,pcVar4);
- pcVar4 = (char *)0x3d;
- TReadScriptFile::readSymbol((TReadScriptFile *)(Ident + 0x1c),'=');
- iVar9 = 9;
- pcVar5 = local_401c;
- pcVar10 = "location";
- do {
- if (iVar9 == 0) break;
- iVar9 = iVar9 + -1;
- uVar11 = *pcVar5 == *pcVar10;
- pcVar5 = pcVar5 + 1;
- pcVar10 = pcVar10 + 1;
- } while ((bool)uVar11);
- if ((bool)uVar11) {
- TReadScriptFile::readString((TReadScriptFile *)(Ident + 0x1c));
- }
- iVar9 = 9;
- pcVar5 = local_401c;
- pcVar10 = "position";
- do {
- if (iVar9 == 0) break;
- iVar9 = iVar9 + -1;
- uVar11 = *pcVar5 == *pcVar10;
- pcVar5 = pcVar5 + 1;
- pcVar10 = pcVar10 + 1;
- } while ((bool)uVar11);
- if ((bool)uVar11) {
- pcVar4 = (char *)this;
- TReadScriptFile::readCoordinate((TReadScriptFile *)(Ident + 0x1c));
- }
- iVar9 = 7;
- pcVar5 = local_401c;
- pcVar10 = "spread";
- do {
- if (iVar9 == 0) break;
- iVar9 = iVar9 + -1;
- uVar11 = *pcVar5 == *pcVar10;
- pcVar5 = pcVar5 + 1;
- pcVar10 = pcVar10 + 1;
- } while ((bool)uVar11);
- if ((bool)uVar11) {
- iVar9 = TReadScriptFile::readNumber((TReadScriptFile *)(Ident + 0x1c));
- this->Spread = iVar9;
- }
- iVar9 = 5;
- pcVar5 = local_401c;
- pcVar10 = "race";
- do {
- if (iVar9 == 0) break;
- iVar9 = iVar9 + -1;
- uVar11 = *pcVar5 == *pcVar10;
- pcVar5 = pcVar5 + 1;
- pcVar10 = pcVar10 + 1;
- } while ((bool)uVar11);
- if ((bool)uVar11) {
- iVar9 = TReadScriptFile::readNumber((TReadScriptFile *)(Ident + 0x1c));
- this->Race = iVar9;
- bVar2 = false;
- if ((0 < this->Race) && (this->Race < 0x200)) {
- bVar2 = true;
- }
- uVar11 = !bVar2;
- if ((bool)uVar11) {
- pcVar4 = "illegal race number";
- TReadScriptFile::error((TReadScriptFile *)(Ident + 0x1c),"illegal race number");
- }
- }
- iVar9 = 6;
- pcVar5 = local_401c;
- pcVar10 = "count";
- do {
- if (iVar9 == 0) break;
- iVar9 = iVar9 + -1;
- uVar11 = *pcVar5 == *pcVar10;
- pcVar5 = pcVar5 + 1;
- pcVar10 = pcVar10 + 1;
- } while ((bool)uVar11);
- if ((bool)uVar11) {
- TReadScriptFile::readSymbol((TReadScriptFile *)(Ident + 0x1c),'(');
- iVar9 = TReadScriptFile::readNumber((TReadScriptFile *)(Ident + 0x1c));
- this->MinCount = iVar9;
- pTVar1 = (TReadScriptFile *)(Ident + 0x1c);
- TReadScriptFile::readSymbol(pTVar1,',');
- iVar9 = TReadScriptFile::readNumber(pTVar1);
- this->MaxCount = iVar9;
- pcVar4 = (char *)0x29;
- TReadScriptFile::readSymbol(pTVar1,')');
- if (this->MaxCount < this->MinCount) {
- pcVar4 = "mincount greater than maxcount";
- TReadScriptFile::error(pTVar1,"mincount greater than maxcount");
- }
- uVar11 = this->MinCount == 0;
- if ((this->MinCount < 0) || (uVar11 = this->MaxCount == 0, this->MaxCount < 1)) {
- pcVar4 = "illegal number of monsters";
- TReadScriptFile::error
- ((TReadScriptFile *)(Ident + 0x1c),"illegal number of monsters");
- }
- }
- iVar9 = 7;
- pcVar5 = local_401c;
- pcVar10 = "radius";
- do {
- if (iVar9 == 0) break;
- iVar9 = iVar9 + -1;
- uVar11 = *pcVar5 == *pcVar10;
- pcVar5 = pcVar5 + 1;
- pcVar10 = pcVar10 + 1;
- } while ((bool)uVar11);
- if ((bool)uVar11) {
- iVar9 = TReadScriptFile::readNumber((TReadScriptFile *)(Ident + 0x1c));
- this->Radius = iVar9;
- }
- iVar9 = 9;
- pcVar5 = local_401c;
- pcVar10 = "lifetime";
- do {
- if (iVar9 == 0) break;
- iVar9 = iVar9 + -1;
- uVar11 = *pcVar5 == *pcVar10;
- pcVar5 = pcVar5 + 1;
- pcVar10 = pcVar10 + 1;
- } while ((bool)uVar11);
- if ((bool)uVar11) {
- iVar9 = TReadScriptFile::readNumber((TReadScriptFile *)(Ident + 0x1c));
- this->Lifetime = iVar9;
- }
- iVar9 = 8;
- pcVar5 = local_401c;
- pcVar10 = "message";
- do {
- if (iVar9 == 0) break;
- iVar9 = iVar9 + -1;
- uVar11 = *pcVar5 == *pcVar10;
- pcVar5 = pcVar5 + 1;
- pcVar10 = pcVar10 + 1;
- } while ((bool)uVar11);
- if ((bool)uVar11) {
- pcVar5 = TReadScriptFile::readString((TReadScriptFile *)(Ident + 0x1c));
- uVar6 = AddDynamicString(pcVar5);
- this->Message = uVar6;
- }
- iVar9 = 10;
- pcVar5 = local_401c;
- pcVar10 = "inventory";
- do {
- if (iVar9 == 0) break;
- iVar9 = iVar9 + -1;
- uVar11 = *pcVar5 == *pcVar10;
- pcVar5 = pcVar5 + 1;
- pcVar10 = pcVar10 + 1;
- } while ((bool)uVar11);
- if ((bool)uVar11) {
- TReadScriptFile::readSymbol((TReadScriptFile *)(Ident + 0x1c),'{');
- do {
- TReadScriptFile::readSymbol((TReadScriptFile *)(Ident + 0x1c),'(');
- iVar9 = this->ExtraItems + 1;
- this->ExtraItems = iVar9;
- this_00 = vector<TItemData>::operator()(&this->ExtraItem,iVar9);
- iVar9 = TReadScriptFile::readNumber((TReadScriptFile *)(Ident + 0x1c));
- ObjectType::setTypeID((ObjectType *)&AttackWave,iVar9);
- ObjectType::setTypeID(&this_00->Type,(int)AttackWave);
- ObjectType::setTypeID(local_402c,(this_00->Type).TypeID);
- TReadScriptFile::readSymbol((TReadScriptFile *)(Ident + 0x1c),',');
- iVar9 = TReadScriptFile::readNumber((TReadScriptFile *)(Ident + 0x1c));
- this_00->Maximum = iVar9;
- TReadScriptFile::readSymbol((TReadScriptFile *)(Ident + 0x1c),',');
- iVar9 = TReadScriptFile::readNumber((TReadScriptFile *)(Ident + 0x1c));
- this_00->Probability = iVar9;
- pcVar4 = (char *)0x29;
- TReadScriptFile::readSymbol((TReadScriptFile *)(Ident + 0x1c),')');
- cVar3 = TReadScriptFile::readSpecial((TReadScriptFile *)(Ident + 0x1c));
- } while (cVar3 != '}');
- }
- }
- if (this->x == 0) {
- pcVar4 = "position expected";
- TReadScriptFile::error((TReadScriptFile *)(Ident + 0x1c),"position expected");
- }
- if (this->Race == -1) {
- pcVar4 = "race expected";
- TReadScriptFile::error((TReadScriptFile *)(Ident + 0x1c),"race expected");
- }
- if (this->MaxCount == 0) {
- pcVar4 = "count expected";
- TReadScriptFile::error((TReadScriptFile *)(Ident + 0x1c),"count expected");
- }
- if (Start < 0) {
- iVar9 = iVar8 + this->Lifetime;
- if (this->Lifetime == 0) {
- iVar9 = iVar8 + 0xe10;
- }
- if (*Duration < iVar9) {
- *Duration = iVar9;
- }
- if (this != (TAttackWave *)0x0) {
- TAttackWave::~TAttackWave(this,(int)pcVar4);
- operator_delete(this);
- }
- }
- else {
- pcVar4 = (char *)(Start + iVar8);
- priority_queue<>::insert(&AttackWaveQueue);
- }
- } while( true );
-}
-
-
-
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-void LoadMonsterRaids(void)
-
-{
- char *__s;
- dirent *DirEntry;
- time_t tVar1;
- DIR *__dirp;
- dirent *pdVar2;
- size_t sVar3;
- long lVar4;
- undefined4 *puVar5;
- int iVar6;
- char *s;
- int iVar7;
- char *pcVar8;
- byte *pbVar9;
- bool bVar10;
- bool bVar11;
- int BigRaidDuration;
- int TieBreaker;
- DIR *WorkDir;
- time_t Now;
- int iStack_2030;
- bool BigRaid;
- int Date;
- int Interval;
- int Duration;
- int Hour;
- int Minute;
- char FileName [4096];
- char BigRaidName [4096];
-
- tVar1 = time((time_t *)0x0);
- // try { // try from 080a4681 to 080a4a1b has its CatchHandler @ 080a4a20
- GetRealTime(&Duration,&Hour);
- iVar7 = (((RebootTime - (Hour + Duration * 0x3c)) + 0x5a0) % 0x5a0) * 0x3c;
- __dirp = opendir(MONSTERPATH);
- if (__dirp == (DIR *)0x0) {
- error("LoadMonsterRaids: Unterverzeichnis %s nicht gefunden.\n",MONSTERPATH);
- puVar5 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar5 = "Cannot load monster raids";
- // WARNING: Subroutine does not return
- __cxa_throw(puVar5,char_const*::typeinfo,0);
- }
- FileName[0xffc] = '\0';
- BigRaidDuration = -1;
- do {
- do {
- pdVar2 = readdir(__dirp);
- if (pdVar2 == (dirent *)0x0) {
- closedir(__dirp);
- if (FileName[0xffc] != '\0') {
- lVar4 = random();
- LoadMonsterRaid(FileName + 0xffc,lVar4 + RoundNr,(bool *)0x0,(int *)0x0,
- (int *)0x0,(int *)0x0);
- }
- return;
- }
- __s = pdVar2->d_name;
- sVar3 = strlen(__s);
- bVar10 = sVar3 < 4;
- bVar11 = sVar3 == 4;
- } while (sVar3 < 5);
- iVar6 = 4;
- pcVar8 = __s + (sVar3 - 4);
- pbVar9 = &DAT_080fe05c;
- do {
- if (iVar6 == 0) break;
- iVar6 = iVar6 + -1;
- bVar10 = (byte)*pcVar8 < *pbVar9;
- bVar11 = *pcVar8 == *pbVar9;
- pcVar8 = pcVar8 + 1;
- pbVar9 = pbVar9 + 1;
- } while (bVar11);
- if ((!bVar10 && !bVar11) == bVar10) {
- sprintf((char *)&Minute,"%s/%s",MONSTERPATH,__s);
- LoadMonsterRaid((char *)&Minute,-1,(bool *)((int)&Now + 3),&stack0xffffdfd0,&Date,
- &Interval);
- print();
- if (0 < iStack_2030) {
- bVar10 = false;
- if ((tVar1 <= iStack_2030) && (bVar10 = true, tVar1 + iVar7 < iStack_2030)) {
- bVar10 = false;
- }
- if ((bVar10) &&
- (LoadMonsterRaid((char *)&Minute,(iStack_2030 + RoundNr) - tVar1,(bool *)0x0,
- (int *)0x0,(int *)0x0,(int *)0x0), Now._3_1_ != '\0')) {
- FileName[0xffc] = '\0';
- BigRaidDuration = 100;
- }
- }
- if (((iStack_2030 == 0) && (Interval <= iVar7)) && (lVar4 = random(), lVar4 < iVar7)) {
- if (Now._3_1_ == '\0') {
- lVar4 = random();
- LoadMonsterRaid((char *)&Minute,lVar4 + RoundNr,(bool *)0x0,(int *)0x0,
- (int *)0x0,(int *)0x0);
- }
- else {
- lVar4 = random();
- if (BigRaidDuration < lVar4) {
- strcpy(FileName + 0xffc,(char *)&Minute);
- BigRaidDuration = lVar4;
- }
- }
- }
- }
- } while( true );
-}
-
-
-
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-void ProcessMonsterRaids(void)
-
-{
- ulong uVar1;
- undefined4 uVar2;
- int iVar3;
- TAttackWave *pTVar4;
- int iVar5;
- ulong *puVar6;
- bool bVar7;
- long lVar8;
- long lVar9;
- TItemData *pTVar10;
- TCreature *pTVar11;
- char *pcVar12;
- priority_queue_entry<> *ppVar13;
- int Count;
- TAttackWave *AttackWave;
- ulong *puVar14;
- int i;
- int i_1;
- int iVar15;
- undefined1 local_cc [36];
- int local_a8;
- int j;
- int Repeat;
- int Amount;
- TCreature *cr;
- int Monsters;
- TCreature___0_ *Monster;
- uint local_8c;
- ulong ExecutionRound;
- int posx;
- int posy;
- int posz;
- Object Obj;
- ulong local_6c [4];
- ulong local_5c [4];
- ulong local_4c [4];
- ulong local_3c [4];
- ulong local_2c;
- Object Bag;
-
- puVar6 = (ulong *)local_cc;
- do {
- puVar14 = puVar6;
- if (AttackWaveQueue.Entries == 0) {
- return;
- }
- puVar14[1] = 1;
- *puVar14 = (ulong)AttackWaveQueue.Entry;
- puVar14[-1] = 0x80a5040;
- ppVar13 = vector<>::operator()((vector<> *)*puVar14,puVar14[1]);
- local_8c = ppVar13->Key;
- puVar14[1] = 1;
- *puVar14 = (ulong)AttackWaveQueue.Entry;
- puVar14[-1] = 0x80a505d;
- ppVar13 = vector<>::operator()((vector<> *)*puVar14,puVar14[1]);
- pTVar4 = ppVar13->Data;
- if (RoundNr < local_8c) {
- return;
- }
- Monster = (TCreature___0_ *)puVar14;
- *puVar14 = (ulong)&AttackWaveQueue;
- puVar14[-1] = 0x80a4a87;
- priority_queue<>::deleteMin((priority_queue<> *)*puVar14);
- uVar1 = pTVar4->Race;
- *puVar14 = 2;
- puVar14[1] = (ulong)"Angriff von Monstern der Rasse %d.\n";
- puVar14[2] = uVar1;
- puVar14[-1] = 0x80a4aa2;
- print();
- if (pTVar4->Message != 0) {
- *puVar14 = pTVar4->Message;
- puVar14[-1] = 0x80a5006;
- pcVar12 = GetDynamicString(*puVar14);
- *puVar14 = 0x13;
- puVar14[2] = (ulong)pcVar12;
- puVar14[1] = (ulong)&DAT_08102a6c;
- puVar14[-1] = 0x80a501e;
- BroadcastMessage(*puVar14,(char *)puVar14[1]);
- }
- puVar14[1] = pTVar4->MaxCount;
- *puVar14 = pTVar4->MinCount;
- puVar14[-1] = 0x80a4abf;
- lVar8 = random();
- cr = (TCreature *)0x0;
- iVar5 = -(lVar8 * 4 + 0xfU & 0xfffffff0);
- Monsters = (int)puVar14 + iVar5 + 0x1c;
- if (0 < lVar8) {
- do {
- *(int *)((int)puVar14 + iVar5 + 4) = pTVar4->Spread;
- *(int *)((int)puVar14 + iVar5) = -pTVar4->Spread;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4b14;
- lVar9 = random();
- ExecutionRound = lVar9 + pTVar4->x;
- *(int *)((int)puVar14 + iVar5 + 4) = pTVar4->Spread;
- *(int *)((int)puVar14 + iVar5) = -pTVar4->Spread;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4b32;
- lVar9 = random();
- posx = lVar9 + pTVar4->y;
- posy = pTVar4->z;
- *(undefined4 *)((int)puVar14 + iVar5 + 0x14) = 0;
- *(undefined4 *)((int)puVar14 + iVar5 + 0x10) = 0;
- *(undefined4 *)((int)puVar14 + iVar5 + 0xc) = 1;
- *(int **)((int)puVar14 + iVar5 + 8) = &posy;
- *(int **)((int)puVar14 + iVar5 + 4) = &posx;
- *(ulong **)((int)puVar14 + iVar5) = &ExecutionRound;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4b6e;
- bVar7 = SearchFreeField(*(int **)((int)puVar14 + iVar5),
- *(int **)((int)puVar14 + iVar5 + 4),
- *(int **)((int)puVar14 + iVar5 + 8),
- *(int *)((int)puVar14 + iVar5 + 0xc),
- *(ushort *)((int)puVar14 + iVar5 + 0x10),
- *(bool *)((int)puVar14 + iVar5 + 0x14));
- if (bVar7) {
- *(int *)((int)puVar14 + iVar5 + 8) = posy;
- *(int *)((int)puVar14 + iVar5 + 4) = posx;
- *(ulong *)((int)puVar14 + iVar5) = ExecutionRound;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4f6c;
- bVar7 = IsProtectionZone();
- if (!bVar7) {
- *(undefined4 *)((int)puVar14 + iVar5 + 0x18) = 1;
- *(undefined4 *)((int)puVar14 + iVar5 + 0x14) = 0;
- *(undefined4 *)((int)puVar14 + iVar5 + 0x10) = 0;
- *(int *)((int)puVar14 + iVar5 + 0xc) = posy;
- *(int *)((int)puVar14 + iVar5 + 8) = posx;
- *(ulong *)((int)puVar14 + iVar5 + 4) = ExecutionRound;
- *(int *)((int)puVar14 + iVar5) = pTVar4->Race;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4faf;
- pTVar11 = CreateMonster(*(int *)((int)puVar14 + iVar5),
- *(int *)((int)puVar14 + iVar5 + 4),
- *(int *)((int)puVar14 + iVar5 + 8),
- *(int *)((int)puVar14 + iVar5 + 0xc),
- *(int *)((int)puVar14 + iVar5 + 0x10),
- *(ulong *)((int)puVar14 + iVar5 + 0x14),
- *(bool *)((int)puVar14 + iVar5 + 0x18));
- *(TCreature **)(Monsters + (int)cr * 4) = pTVar11;
- if (pTVar11 != (TCreature *)0x0) {
- if (pTVar4->Lifetime != 0) {
- pTVar11->LifeEndRound = pTVar4->Lifetime + RoundNr;
- }
- *(int *)(*(int *)(Monsters + (int)cr * 4) + 0x288) = pTVar4->Radius;
- cr = (TCreature *)((int)&cr->_vptr_TCreature + 1);
- }
- }
- }
- lVar8 = lVar8 + -1;
- } while (lVar8 != 0);
- }
- iVar15 = 1;
- if (0 < pTVar4->ExtraItems) {
- do {
- if ((int)cr < 1) break;
- *(int *)((int)puVar14 + iVar5 + 4) = iVar15;
- *(vector<TItemData> **)((int)puVar14 + iVar5) = &pTVar4->ExtraItem;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4b9c;
- pTVar10 = vector<TItemData>::operator()
- (*(vector<TItemData> **)((int)puVar14 + iVar5),
- *(int *)((int)puVar14 + iVar5 + 4));
- *(undefined4 *)((int)puVar14 + iVar5) = 0;
- *(undefined4 *)((int)puVar14 + iVar5 + 4) = 999;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4bb2;
- lVar8 = random();
- pTVar11 = cr;
- if (lVar8 <= pTVar10->Probability) {
- *(undefined4 *)((int)puVar14 + iVar5) = 0;
- *(undefined1 **)((int)puVar14 + iVar5 + 4) =
- (undefined1 *)((int)&pTVar11[-1].Connection + 3);
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4bff;
- lVar8 = random();
- Amount = *(int *)(Monsters + lVar8 * 4);
- *(undefined4 *)((int)puVar14 + iVar5 + 8) = 3;
- uVar2 = *(undefined4 *)(Amount + 0x208);
- *(ulong **)((int)puVar14 + iVar5) = &local_2c;
- *(undefined4 *)((int)puVar14 + iVar5 + 4) = uVar2;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4c31;
- GetBodyObject(*(ulong *)((int)puVar14 + iVar5),
- *(int *)((int)puVar14 + iVar5 + 4));
- local_3c[0] = NONE.ObjectID;
- if (local_2c == NONE.ObjectID) {
- *(undefined4 *)((int)puVar14 + iVar5 + 4) = 0xe;
- *(ulong **)((int)puVar14 + iVar5) = local_6c;
- // try { // try from 080a4c4f to 080a4c9d has its CatchHandler @ 080a506a
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4c54;
- GetSpecialObject(*(SPECIALMEANING *)((int)puVar14 + iVar5));
- *(undefined4 *)((int)puVar14 + iVar5 + 8) = 3;
- *(undefined4 *)((int)puVar14 + iVar5 + 4) = *(undefined4 *)(Amount + 0x208);
- *(int **)((int)puVar14 + iVar5) = &posz;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4c7a;
- GetBodyContainer(*(ulong *)((int)puVar14 + iVar5),
- *(int *)((int)puVar14 + iVar5 + 4));
- *(undefined4 *)((int)puVar14 + iVar5 + 0xc) = 0;
- *(ulong **)((int)puVar14 + iVar5 + 8) = local_6c;
- *(int **)((int)puVar14 + iVar5 + 4) = &posz;
- *(ulong **)((int)puVar14 + iVar5) = local_5c;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4c9e;
- Create(*(Object **)((int)puVar14 + iVar5),
- *(ObjectType **)((int)puVar14 + iVar5 + 4),
- *(ulong *)((int)puVar14 + iVar5 + 8));
- local_2c = local_5c[0];
- local_4c[0] = local_5c[0];
- }
- iVar3 = pTVar10->Maximum;
- *(undefined4 *)((int)puVar14 + iVar5) = 1;
- *(int *)((int)puVar14 + iVar5 + 4) = iVar3;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4cbd;
- Repeat = random();
- *(int *)((int)puVar14 + iVar5 + 0xc) = (pTVar10->Type).TypeID;
- iVar3 = Repeat;
- *(undefined4 *)((int)puVar14 + iVar5) = 2;
- *(char **)((int)puVar14 + iVar5 + 4) = "Verteile %d Objekte vom Typ %d.\n";
- *(int *)((int)puVar14 + iVar5 + 8) = iVar3;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4ce7;
- print();
- j = 1;
- *(undefined4 *)((int)puVar14 + iVar5 + 4) = 6;
- *(TItemData **)((int)puVar14 + iVar5) = pTVar10;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4d02;
- bVar7 = ObjectType::getFlag(*(ObjectType **)((int)puVar14 + iVar5),
- *(FLAG *)((int)puVar14 + iVar5 + 4));
- iVar3 = Repeat;
- if (!bVar7) {
- Repeat = 0;
- j = iVar3;
- }
- local_a8 = 0;
- if (0 < j) {
- do {
- posz = 0;
- *(undefined4 *)((int)puVar14 + iVar5 + 4) = 0x37;
- *(TItemData **)((int)puVar14 + iVar5) = pTVar10;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4d4b;
- bVar7 = ObjectType::getFlag(*(ObjectType **)((int)puVar14 + iVar5),
- *(FLAG *)((int)puVar14 + iVar5 + 4));
- if (bVar7) {
-LAB_080a4d67:
- iVar3 = (pTVar10->Type).TypeID;
- *(ulong **)((int)puVar14 + iVar5) = local_4c;
- *(int *)((int)puVar14 + iVar5 + 4) = iVar3;
- // try { // try from 080a4d73 to 080a4d9e has its CatchHandler @ 080a50b2
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4d78;
- ObjectType::setTypeID
- (*(ObjectType **)((int)puVar14 + iVar5),
- *(int *)((int)puVar14 + iVar5 + 4));
- local_3c[0] = local_2c;
- *(undefined4 *)((int)puVar14 + iVar5 + 0xc) = 0;
- *(ulong **)((int)puVar14 + iVar5 + 8) = local_4c;
- *(ulong **)((int)puVar14 + iVar5 + 4) = local_3c;
- *(ulong **)((int)puVar14 + iVar5) = local_5c;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4d9f;
- Create(*(Object **)((int)puVar14 + iVar5),
- *(ObjectType **)((int)puVar14 + iVar5 + 4),
- *(ulong *)((int)puVar14 + iVar5 + 8));
- }
- else {
- *(undefined4 *)((int)puVar14 + iVar5 + 4) = 0x38;
- *(TItemData **)((int)puVar14 + iVar5) = pTVar10;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4d5f;
- bVar7 = ObjectType::getFlag(*(ObjectType **)((int)puVar14 + iVar5),
- *(FLAG *)((int)puVar14 + iVar5 + 4));
- if (bVar7) goto LAB_080a4d67;
- *(undefined4 *)((int)puVar14 + iVar5 + 4) = 0x39;
- *(TItemData **)((int)puVar14 + iVar5) = pTVar10;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4e88;
- bVar7 = ObjectType::getFlag(*(ObjectType **)((int)puVar14 + iVar5),
- *(FLAG *)((int)puVar14 + iVar5 + 4));
- if (bVar7) goto LAB_080a4d67;
- *(undefined4 *)((int)puVar14 + iVar5 + 4) = 0x3a;
- *(TItemData **)((int)puVar14 + iVar5) = pTVar10;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4ea0;
- bVar7 = ObjectType::getFlag(*(ObjectType **)((int)puVar14 + iVar5),
- *(FLAG *)((int)puVar14 + iVar5 + 4));
- if (bVar7) goto LAB_080a4d67;
- *(undefined4 *)((int)puVar14 + iVar5 + 4) = 0x3b;
- *(TItemData **)((int)puVar14 + iVar5) = pTVar10;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4eb8;
- bVar7 = ObjectType::getFlag(*(ObjectType **)((int)puVar14 + iVar5),
- *(FLAG *)((int)puVar14 + iVar5 + 4));
- if (bVar7) goto LAB_080a4d67;
- *(undefined4 *)((int)puVar14 + iVar5 + 4) = 0x36;
- *(TItemData **)((int)puVar14 + iVar5) = pTVar10;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4ed0;
- bVar7 = ObjectType::getFlag(*(ObjectType **)((int)puVar14 + iVar5),
- *(FLAG *)((int)puVar14 + iVar5 + 4));
- if (bVar7) goto LAB_080a4d67;
- *(undefined4 *)((int)puVar14 + iVar5 + 4) = 0x34;
- *(TItemData **)((int)puVar14 + iVar5) = pTVar10;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4ee8;
- bVar7 = ObjectType::getFlag(*(ObjectType **)((int)puVar14 + iVar5),
- *(FLAG *)((int)puVar14 + iVar5 + 4));
- if (bVar7) goto LAB_080a4d67;
- *(undefined4 *)((int)puVar14 + iVar5 + 4) = 0x35;
- *(TItemData **)((int)puVar14 + iVar5) = pTVar10;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4f00;
- bVar7 = ObjectType::getFlag(*(ObjectType **)((int)puVar14 + iVar5),
- *(FLAG *)((int)puVar14 + iVar5 + 4));
- if (bVar7) goto LAB_080a4d67;
- iVar3 = (pTVar10->Type).TypeID;
- *(ulong **)((int)puVar14 + iVar5) = local_4c;
- *(int *)((int)puVar14 + iVar5 + 4) = iVar3;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4f19;
- ObjectType::setTypeID
- (*(ObjectType **)((int)puVar14 + iVar5),
- *(int *)((int)puVar14 + iVar5 + 4));
- iVar3 = Repeat;
- *(ulong **)((int)puVar14 + iVar5 + 8) = local_4c;
- *(int *)((int)puVar14 + iVar5 + 0xc) = iVar3;
- *(undefined4 *)((int)puVar14 + iVar5 + 4) =
- *(undefined4 *)(Amount + 0x208);
- *(ulong **)((int)puVar14 + iVar5) = local_5c;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4f45;
- CreateAtCreature(*(ulong *)((int)puVar14 + iVar5),
- *(ObjectType **)((int)puVar14 + iVar5 + 4),
- *(ulong *)((int)puVar14 + iVar5 + 8));
- }
- posz = local_5c[0];
- local_6c[0] = local_5c[0];
- *(int **)((int)puVar14 + iVar5 + 4) = &posz;
- *(ulong **)((int)puVar14 + iVar5) = local_6c;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4dbd;
- Object::getContainer(*(Object **)((int)puVar14 + iVar5));
- *(ulong **)((int)puVar14 + iVar5 + 4) = local_6c;
- *(ulong **)((int)puVar14 + iVar5) = local_5c;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4dd2;
- Object::getObjectType(*(Object **)((int)puVar14 + iVar5));
- if (local_5c[0] == 0) {
- uVar2 = *(undefined4 *)(Amount + 0x280);
- *(undefined **)((int)puVar14 + iVar5) = &DAT_081025a0;
- *(undefined4 *)((int)puVar14 + iVar5 + 4) = uVar2;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4e5a;
- error(*(char **)((int)puVar14 + iVar5));
- local_5c[0] = posz;
- *(undefined4 *)((int)puVar14 + iVar5 + 4) = 0xffffffff;
- *(ulong **)((int)puVar14 + iVar5) = local_5c;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4e73;
- Delete(*(Object **)((int)puVar14 + iVar5),
- *(int *)((int)puVar14 + iVar5 + 4));
- }
- local_a8 = local_a8 + 1;
- } while (local_a8 < j);
- }
- local_6c[0] = local_2c;
- *(ulong **)((int)puVar14 + iVar5 + 4) = local_6c;
- *(int **)((int)puVar14 + iVar5) = &posz;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4e0c;
- GetFirstContainerObject(*(Object **)((int)puVar14 + iVar5));
- local_5c[0] = NONE.ObjectID;
- if (posz == NONE.ObjectID) {
- local_4c[0] = local_2c;
- *(undefined4 *)((int)puVar14 + iVar5 + 4) = 0xffffffff;
- *(ulong **)((int)puVar14 + iVar5) = local_4c;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4e39;
- Delete(*(Object **)((int)puVar14 + iVar5),*(int *)((int)puVar14 + iVar5 + 4)
- );
- }
- }
- iVar15 = iVar15 + 1;
- } while (iVar15 <= pTVar4->ExtraItems);
- }
- puVar6 = (ulong *)Monster;
- if (pTVar4 != (TAttackWave *)0x0) {
- *(TAttackWave **)((int)puVar14 + iVar5) = pTVar4;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4bde;
- TAttackWave::~TAttackWave
- (*(TAttackWave **)((int)puVar14 + iVar5),*(int *)((int)puVar14 + iVar5 + 4));
- *(TAttackWave **)((int)puVar14 + iVar5) = pTVar4;
- *(undefined4 *)((int)puVar14 + iVar5 + -4) = 0x80a4be6;
- operator_delete(*(void **)((int)puVar14 + iVar5));
- puVar6 = (ulong *)Monster;
- }
- } while( true );
-}
-
void __tcf_0(void *param_1)
{
diff --git a/reference/types.hh b/reference/types.hh index c711831..f3ce69d 100644 --- a/reference/types.hh +++ b/reference/types.hh @@ -89,21 +89,6 @@ struct TWaitinglistEntry { bool Sleeping; }; -struct TAttackWave { - int x; - int y; - int z; - int Spread; - int Race; - int MinCount; - int MaxCount; - int Radius; - int Lifetime; - ulong Message; - int ExtraItems; - struct vector<TItemData> ExtraItem; -}; - struct TReportedStatement { ulong StatementID; ulong TimeStamp; diff --git a/src/containers.hh b/src/containers.hh index ba7e3cd..85dcfde 100644 --- a/src/containers.hh +++ b/src/containers.hh @@ -3,11 +3,21 @@ #include "common.hh" +// NOTE(fusion): All containers are automatically managed by their constructors +// and destructors, meaning raw copies could result in memory corruption through +// double frees, use after frees, etc... To avoid that, we need to make them all +// non copyable. +#define NONCOPYABLE(Type) \ + Type(const Type &Other) = delete; \ + void operator=(const Type &Other) = delete; + // NOTE(fusion): What the actual fuck. This is an ever growing dynamic array // with each access through `operator()` growing it to make sure the requested // index is valid, even for negative indices. template<typename T> struct vector{ + NONCOPYABLE(vector) + vector(int min, int max, int block){ int space = (max - min) + 1; if(space < 1){ @@ -128,6 +138,8 @@ struct priority_queue_entry{ template<typename K, typename T> struct priority_queue{ + NONCOPYABLE(priority_queue) + priority_queue(int capacity, int increment){ Entry = new vector<priority_queue_entry<K, T>>(1, capacity, increment); Entries = 0; @@ -205,6 +217,8 @@ struct priority_queue{ template<typename T> struct matrix{ + NONCOPYABLE(matrix) + matrix(int xmin, int xmax, int ymin, int ymax){ int dx = (xmax - xmin) + 1; int dy = (ymax - ymin) + 1; @@ -273,6 +287,8 @@ struct matrix{ template<typename T> struct matrix3d{ + NONCOPYABLE(matrix3d) + matrix3d(int xmin, int xmax, int ymin, int ymax, int zmin, int zmax){ int dx = (xmax - xmin) + 1; int dy = (ymax - ymin) + 1; @@ -351,6 +367,8 @@ struct listnode{ template<typename T> struct list{ + NONCOPYABLE(list) + list(void){ firstNode = NULL; lastNode = NULL; @@ -409,6 +427,8 @@ struct list{ template<typename T> struct fifo{ + NONCOPYABLE(fifo) + fifo(int InitialSize){ ASSERT(InitialSize > 0); this->Entry = new T[InitialSize]; @@ -490,6 +510,8 @@ struct storeunit{ // It is also known as a slab allocator. template<typename T, usize N> struct store{ + NONCOPYABLE(store) + store(void){ this->Units = new list<storeunit<T, N>>; this->firstFreeItem = NULL; @@ -154,6 +154,28 @@ struct TPlayerData { int NumberOfMutings; }; +// TAttackWave +// ============================================================================= +struct TAttackWave { + TAttackWave(void); + ~TAttackWave(void); + + // DATA + // ================= + int x; + int y; + int z; + int Spread; + int Race; + int MinCount; + int MaxCount; + int Radius; + int Lifetime; + uint32 Message; + int ExtraItems; + vector<TItemData> ExtraItem; +}; + // TSkillBase // ============================================================================= struct TSkill{ @@ -722,8 +744,6 @@ struct TPlayer: TCreature { // ============================================================================= #define MAX_RACES 512 extern TRaceData RaceData[MAX_RACES]; -extern int KilledCreatures[MAX_RACES]; -extern int KilledPlayers[MAX_RACES]; extern priority_queue<uint32, uint32> ToDoQueue; bool IsCreaturePlayer(uint32 CreatureID); @@ -752,9 +772,15 @@ bool GetRaceNoParalyze(int Race); int GetRaceSummonCost(int Race); int GetRacePoison(int Race); bool GetRaceUnpushable(int Race); - TOutfit ReadOutfit(TReadScriptFile *Script); void WriteOutfit(TReadScriptFile *Script, TOutfit Outfit); +void LoadRace(const char *FileName); +void LoadRaces(void); + +void LoadMonsterRaid(const char *FileName, int Start, + bool *Type, int *Date, int *Interval, int *Duration); +void LoadMonsterRaids(void); +void ProcessMonsterRaids(void); // crskill.cc // ============================================================================= diff --git a/src/crmain.cc b/src/crmain.cc index 48d31be..5d0f2f3 100644 --- a/src/crmain.cc +++ b/src/crmain.cc @@ -5,18 +5,20 @@ #include "stubs.hh" -TRaceData RaceData[MAX_RACES]; -int KilledCreatures[MAX_RACES]; -int KilledPlayers[MAX_RACES]; +#include <dirent.h> +#include <time.h> +TRaceData RaceData[MAX_RACES]; priority_queue<uint32, uint32> ToDoQueue(5000, 1000); -//priority_queue<uint32, TAttackWave*> AttackWaveQueue(100, 100); static uint32 NextCreatureID; static int FirstFreeCreature; static TCreature *HashList[1000]; static matrix<uint32> *FirstChainCreature; static vector<TCreature*> CreatureList(0, 10000, 1000); +static priority_queue<uint32, TAttackWave*> AttackWaveQueue(100, 100); +static int KilledCreatures[MAX_RACES]; +static int KilledPlayers[MAX_RACES]; // TFindCreatures // ============================================================================= @@ -1332,10 +1334,11 @@ TOutfit ReadOutfit(TReadScriptFile *Script){ memcpy(Outfit.Colors, Script->readBytesequence(), sizeof(Outfit.Colors)); } Script->readSymbol(')'); + return Outfit; } // TODO(fusion): Probably move this somewhere else? -void WriteOutfit(TReadScriptFile *Script, TOutfit Outfit){ +void WriteOutfit(TWriteScriptFile *Script, TOutfit Outfit){ Script->writeText("("); Script->writeNumber(Outfit.OutfitID); Script->writeText(","); @@ -1361,7 +1364,7 @@ void LoadRace(const char *FileName){ Script.readSymbol('='); int RaceNumber = Script.readNumber(); - if(!IsRaceValid(Race)){ + if(!IsRaceValid(RaceNumber)){ Script.error("illegal race number"); } @@ -1389,7 +1392,7 @@ void LoadRace(const char *FileName){ }else if(strcmp(Identifier, "article") == 0){ strcpy(Race->Article, Script.readString()); }else if(strcmp(Identifier, "outfit") == 0){ - Race->Outfit = ReadOutfit(Script); + Race->Outfit = ReadOutfit(&Script); }else if(strcmp(Identifier, "corpse") == 0){ int CorpseTypeID = Script.readNumber(); Race->MaleCorpse = CorpseTypeID; @@ -1512,10 +1515,10 @@ void LoadRace(const char *FileName){ }else if(strcmp(Identifier, "inventory") == 0){ Script.readSymbol('{'); do{ - Script.readSymbol('('); // NOTE(fusion): Items are indexed from 1. Race->Items += 1; TItemData *ItemData = Race->Item.at(Race->Items); + Script.readSymbol('('); ItemData->Type = Script.readNumber(); Script.readSymbol(','); ItemData->Maximum = Script.readNumber(); @@ -1526,6 +1529,7 @@ void LoadRace(const char *FileName){ }else if(strcmp(Identifier, "spells") == 0){ Script.readSymbol('{'); do{ + // NOTE(fusion): Spells are indexed from 1. Race->Spells += 1; TSpellData *SpellData = Race->Spell.at(Race->Spells); @@ -1636,7 +1640,7 @@ void LoadRace(const char *FileName){ }else if(strcmp(SpellImpact, "outfit") == 0){ SpellData->Impact = IMPACT_OUTFIT; Script.readSymbol('('); - TOutfit Outfit = ReadOutfit(Script); + TOutfit Outfit = ReadOutfit(&Script); SpellData->ImpactParam1 = Outfit.OutfitID; SpellData->ImpactParam2 = (int)Outfit.PackedData; Script.readSymbol(','); @@ -1665,7 +1669,7 @@ void LoadRace(const char *FileName){ } }while(Script.readSpecial() != '}'); }else{ - Script.error("unknown race field"); + Script.error("unknown race property"); } } } @@ -1697,7 +1701,401 @@ void LoadRaces(void){ // Monster Raid // ============================================================================= -void LoadMonsterRaids(void); //TODO +TAttackWave::TAttackWave(void) : + ExtraItem(1, 5, 5) +{ + this->x = 0; + this->y = 0; + this->z = 0; + this->Spread = 0; + this->Race = -1; + this->MinCount = 0; + this->MaxCount = 0; + this->Radius = INT_MAX; + this->Lifetime = 0; + this->Message = 0; + this->ExtraItems = 0; +} + +TAttackWave::~TAttackWave(void){ + if(this->Message != 0){ + DeleteDynamicString(this->Message); + } +} + +void LoadMonsterRaid(const char *FileName, int Start, + bool *Type, int *Date, int *Interval, int *Duration){ + if(FileName == NULL){ + error("LoadMonsterRaid: Dateiname ist NULL.\n"); + throw "cannot load monster raid"; + } + + // TODO(fusion): The original function would only write to these output + // variables when `Start` was negative. Instead, we assign dummy variables + // if any of the pointers is NULL to allow for any reads and writes while + // loading the raid. + bool DummyType; + int DummyDate; + int DummyInterval; + int DummyDuration; + if(Type == NULL) { Type = &DummyType; } + if(Date == NULL) { Date = &DummyDate; } + if(Interval == NULL) { Interval = &DummyInterval; } + if(Duration == NULL) { Duration = &DummyDuration; } + + *Type = false; + *Date = 0; + *Interval = 0; + *Duration = 0; + + if(Start >= 0){ + print(1, "Plane Raid %s ein für Runde %d.\n", FileName, Start); + } + + // NOTE(fusion): We expect the first few attributes describing the raid to + // be in an exact order, followed by attack waves. Attack wave attributes + // don't need to be in any specific order but specifying `Delay` will wrap + // the previous wave (if any) and start a new one. + + TReadScriptFile Script; + Script.open(FileName); + + // NOTE(fusion): Optional `Description` attribute. + Script.nextToken(); + if(strcmp(Script.getIdentifier(), "description") == 0){ + Script.readSymbol('='); + Script.readString(); + Script.nextToken(); + } + + if(strcmp(Script.getIdentifier(), "type") == 0){ + // NOTE(fusion): The type can be either "BigRaid" or "SmallRaid" so it uses + // a boolean for `Type` to tell whether it is a big raid or not. It could be + // renamed to `BigRaid` or something. + Script.readSymbol('='); + *Type = (strcmp(Script.readIdentifier(), "bigraid") == 0); + }else{ + Script.error("type expected"); + } + + Script.nextToken(); + if(strcmp(Script.getIdentifier(), "date") == 0){ + Script.readSymbol('='); + *Date = Script.getNumber(); + }else if(strcmp(Script.getIdentifier(), "interval") == 0){ + Script.readSymbol('='); + *Interval = Script.getNumber(); + }else{ + Script.error("date or interval expected"); + } + + Script.nextToken(); + while(Script.Token != ENDOFFILE){ + if(strcmp(Script.getIdentifier(), "delay") == 0){ + Script.error("delay expected"); + } + + Script.readSymbol('='); + int Delay = Script.readNumber(); + TAttackWave *Wave = new TAttackWave; + while(true){ + Script.nextToken(); + if(Script.Token == ENDOFFILE){ + break; + } + + if(strcmp(Script.getIdentifier(), "delay") == 0){ + break; + } + + char Identifier[MAX_IDENT_LENGTH]; + strcpy(Identifier, Script.getIdentifier()); + Script.readSymbol('='); + if(strcmp(Identifier, "location") == 0){ + Script.readString(); + }else if(strcmp(Identifier, "position") == 0){ + Script.readCoordinate(&Wave->x, &Wave->y, &Wave->z); + }else if(strcmp(Identifier, "spread") == 0){ + Wave->Spread = Script.readNumber(); + }else if(strcmp(Identifier, "race") == 0){ + Wave->Race = Script.readNumber(); + if(!IsRaceValid(Wave->Race)){ + Script.error("illegal race number"); + } + }else if(strcmp(Identifier, "count") == 0){ + Script.readSymbol('('); + Wave->MinCount = Script.readNumber(); + Script.readSymbol(','); + Wave->MaxCount = Script.readNumber(); + Script.readSymbol(')'); + + if(Wave->MaxCount < Wave->MinCount){ + Script.error("mincount greater than maxcount"); + } + + if(Wave->MinCount < 0 || Wave->MaxCount < 1){ + Script.error("illegal number of monsters"); + } + }else if(strcmp(Identifier, "radius") == 0){ + Wave->Radius = Script.readNumber(); + }else if(strcmp(Identifier, "lifetime") == 0){ + Wave->Lifetime = Script.readNumber(); + }else if(strcmp(Identifier, "message") == 0){ + Wave->Message = AddDynamicString(Script.readString()); + }else if(strcmp(Identifier, "inventory") == 0){ + Script.readSymbol('{'); + do{ + // NOTE(fusion): Items are indexed from 1. + Wave->ExtraItems += 1; + TItemData *ItemData = Wave->ExtraItem.at(Wave->ExtraItems); + Script.readSymbol('('); + ItemData->Type = Script.readNumber(); + Script.readSymbol(','); + ItemData->Maximum = Script.readNumber(); + Script.readSymbol(','); + ItemData->Probability = Script.readNumber(); + Script.readSymbol(')'); + }while(Script.readSpecial() != '}'); + }else{ + Script.error("unknown attack wave property"); + } + } + + if(Wave->x == 0){ + Script.error("position expected"); + } + + if(Wave->Race == -1){ + Script.error("race expected"); + } + + if(Wave->MaxCount == 0){ + Script.error("count expected"); + } + + int WaveEnd = Delay + (Wave->Lifetime != 0 ? Wave->Lifetime : 3600); + if(*Duration < WaveEnd){ + *Duration = WaveEnd; + } + + if(Start >= 0){ + AttackWaveQueue.insert(Start + Delay, Wave); + }else{ + delete Wave; + } + } + + Script.close(); +} + +void LoadMonsterRaids(void){ + DIR *MonsterDir = opendir(MONSTERPATH); + if(MonsterDir == NULL){ + error("LoadMonsterRaids: Unterverzeichnis %s nicht gefunden.\n", MONSTERPATH); + throw "Cannot load monster raids"; + } + + // TODO(fusion): The `Date` attribute used by raid files is a unix timestamp + // which is usually what `time(NULL)` returns. This should work fine until + // 2038 when the timestamp value exceeds the capacity of a 32-bit signed + // integer. + int Now = (int)std::min<time_t>(time(NULL), INT_MAX); + + int Hour, Minute; + GetRealTime(&Hour, &Minute); + + int SecondsToReboot = (RebootTime - (Hour * 60 + Minute)) * 60; + if(SecondsToReboot < 0){ + SecondsToReboot += 86400; + } + + char BigRaidName[4096]; + int BigRaidDuration = 0; + int BigRaidTieBreaker = -1; + + char FileName[4096]; + while(dirent *DirEntry = readdir(MonsterDir)){ + const char *FileExt = findLast(DirEntry->d_name, '.'); + if(FileExt != NULL && strcmp(FileExt, ".evt") == 0){ + snprintf(FileName, sizeof(FileName), "%s/%s", MONSTERPATH, DirEntry->d_name); + + bool BigRaid; + int Date, Interval, Duration; + LoadMonsterRaid(FileName, -1, &BigRaid, &Date, &Interval, &Duration); + print(1, "Raid %s: Date %d, Interval %d, Duration %d\n", + FileName, Date, Interval, Duration); + + if(Date > 0){ + if(Now <= Date && Date <= (Now + SecondsToReboot)){ + int Start = RoundNr + (Date - Now); + LoadMonsterRaid(FileName, Start, NULL, NULL, NULL, NULL); + if(BigRaid){ + BigRaidName[0] = 0; + BigRaidDuration = 0; + BigRaidTieBreaker = 100; + } + } + }else if(Duration <= SecondsToReboot){ + // NOTE(fusion): `Interval` specifies an average raid interval + // in seconds. With this function being called at startup, usually + // after a reboot, we can expect `SecondsToReboot` to be close to + // a day very regularly. Meaning we can approximate the condition + // below to `random(1, AverageIntervalDays) == 1` which hopefully + // makes more sense. + if(random(0, Interval - 1) < SecondsToReboot){ + if(!BigRaid){ + int Start = RoundNr + random(0, SecondsToReboot - Duration); + LoadMonsterRaid(FileName, Start, NULL, NULL, NULL, NULL); + }else{ + int TieBreaker = random(0, 99); + if(TieBreaker > BigRaidTieBreaker){ + strcpy(BigRaidName, FileName); + BigRaidDuration = Duration; + BigRaidTieBreaker = TieBreaker; + } + } + } + } + } + } + + closedir(MonsterDir); + + if(BigRaidName[0] != 0){ + int Start = RoundNr + random(0, SecondsToReboot - BigRaidDuration); + LoadMonsterRaid(BigRaidName, Start, NULL, NULL, NULL, NULL); + } +} + +void ProcessMonsterRaids(void){ + while(AttackWaveQueue.Entries > 0){ + auto Entry = *AttackWaveQueue.Entry->at(1); + uint32 ExecutionRound = Entry.Key; + TAttackWave *Wave = Entry.Data; + if(ExecutionRound > RoundNr){ + break; + } + + AttackWaveQueue.deleteMin(); + print(2, "Angriff von Monstern der Rasse %d.\n", Wave->Race); + if(Wave->Message != 0){ + BroadcastMessage(TALK_EVENT_MESSAGE, "%s", GetDynamicString(Wave->Message)); + } + + int NumSpawned = 0; + TCreature *Spawned[64] = {}; + + // NOTE(fusion): The original function would use `alloca` to allocate the + // buffer for spawned creatures. Inspecting some raid files, the maximum + // count I could find was 40. I don't think it is realistic for this number + // to get much higher, mostly because you can always split a large wave + // into multiple smaller ones, and because going crazy with alloca could + // cause the stack to blow up. + int Count = random(Wave->MinCount, Wave->MaxCount); + if(Count > NARRAY(Spawned)){ + Count = NARRAY(Spawned); + } + + for(int i = 0; i < Count; i += 1){ + int SpawnX = Wave->x + random(-Wave->Spread, Wave->Spread); + int SpawnY = Wave->y + random(-Wave->Spread, Wave->Spread); + int SpawnZ = Wave->z; + if(!SearchFreeField(&SpawnX, &SpawnY, &SpawnZ, 1, 0, false) + || IsProtectionZone(SpawnX, SpawnY, SpawnZ)){ + continue; + } + + TCreature *Creature = CreateMonster(Wave->Race, SpawnX, SpawnY, SpawnZ, 0, 0, true); + if(Creature != NULL){ + Creature->Radius = Wave->Radius; + if(Wave->Lifetime != 0){ + Creature->LifeEndRound = RoundNr + Wave->Lifetime; + } + + Spawned[NumSpawned] = Creature; + NumSpawned += 1; + } + } + + if(NumSpawned > 0){ + int ExtraItems = Wave->ExtraItems; + for(int i = 1; i <= ExtraItems; i += 1){ + TItemData *ItemData = Wave->ExtraItem.at(i); + if(random(0, 999) > ItemData->Probability){ + continue; + } + + TCreature *Creature = Spawned[random(0, NumSpawned - 1)]; + Object Bag = GetBodyObject(Creature->ID, 3); // BAG ? + if(Bag == NONE){ + try{ + Bag = Create(GetBodyContainer(Creature->ID, 3), + GetSpecialObject(INVENTORY_CONTAINER), + 0); + }catch(RESULT r){ + error("ProcessMonsterRaids: Exception %d bei Rasse %d" + " beim Erstellen des Rucksacks.\n", r, Wave->Race); + continue; + } + } + + ObjectType ItemType = ItemData->Type; + int Amount = random(1, ItemData->Maximum); + int Repeat = 1; + if(!ItemType.getFlag(CUMULATIVE)){ + Repeat = Amount; + Amount = 0; + } + + print(2, "Verteile %d Objekte vom Typ %d.\n", Amount, ItemType.TypeID); + for(int j = 0; j < Repeat; j += 1){ + // TODO(fusion): What's the difference between using `Create` + // and `CreateAtCreature` here? Maybe it checks carry strength, + // but then why? Don't they have some check to make sure items + // are not dropped onto the map? This is very confusing and + // using exception handlers all over the place doesn't help + // either. + Object Item = NONE; + try{ + // TODO(fusion): Possibly an inlined function to check for + // weapons or equipment? + if(ItemType.getFlag(WEAPON) + || ItemType.getFlag(SHIELD) + || ItemType.getFlag(BOW) + || ItemType.getFlag(THROW) + || ItemType.getFlag(WAND) + || ItemType.getFlag(WEAROUT) + || ItemType.getFlag(EXPIRE) + || ItemType.getFlag(EXPIRESTOP)){ + Item = Create(Bag, ItemType, 0); + }else{ + Item = CreateAtCreature(Creature->ID, ItemType, Amount); + } + }catch(RESULT r){ + error("ProcessMonsterRaids: Exception %d bei Rasse %d, ggf." + " CarryStrength erhöhen.\n", r, Wave->Race); + break; + } + + if(Item.getContainer().getObjectType().isMapContainer()){ + error("ProcessMonsterRaids: Objekt fällt auf die Karte." + " CarryStrength für Rasse %d erhöhen.\n", Wave->Race); + Delete(Item, -1); + // TODO(fusion): Should probably stop this inner loop here. + } + } + + // NOTE(fusion): `Bag` could be empty if we failed to add any + // items to it in the loop above. + if(GetFirstContainerObject(Bag) == NONE){ + Delete(Bag, -1); + } + } + } + + delete Wave; + } +} // Initialization // ============================================================================= diff --git a/src/objects.cc b/src/objects.cc index 51171f0..198a11d 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -576,7 +576,7 @@ static void LoadObjects(void){ } } }else{ - Script.error("Unknown object type field"); + Script.error("Unknown object type property"); } } } diff --git a/src/stubs.hh b/src/stubs.hh index 3495a59..d936ab5 100644 --- a/src/stubs.hh +++ b/src/stubs.hh @@ -28,12 +28,13 @@ extern void ChallengeMonster(TCreature *Challenger, TCreature *Monster); extern int CountInventoryObjects(uint32 CreatureID, ObjectType Type, uint32 Value); extern Object Create(Object Con, ObjectType Type, uint32 Value); extern Object CreateAtCreature(uint32 CreatureID, ObjectType Type, uint32 Value); -extern void CreateMonster(int Race, int x, int y, int z, int Home, uint32 Master, bool ShowEffect); +extern TCreature *CreateMonster(int Race, int x, int y, int z, int Home, uint32 Master, bool ShowEffect); extern void CreatePlayerList(bool Online); extern void CreatePool(Object Con, ObjectType Type, uint32 Value); extern void Delete(Object Obj, int Count); extern bool FieldPossible(int x, int y, int z, int FieldType); extern Object GetBodyObject(uint32 CreatureID, int Position); +extern Object GetBodyContainer(uint32 CreatureID, int Position); extern void GetExitPosition(uint16 HouseID, int *x, int *y, int *z); extern TConnection *GetFirstConnection(void); extern TConnection *GetNextConnection(void); @@ -62,7 +63,6 @@ extern void ProcessCommunicationControl(void); extern void ProcessConnections(void); extern void ProcessCronSystem(void); extern void ProcessMonsterhomes(void); -extern void ProcessMonsterRaids(void); extern void ProcessReaderThreadReplies(TRefreshSectorFunction *RefreshSector, TSendMailsFunction *SendMails); extern void ProcessWriterThreadReplies(void); extern void ReceiveData(void); |
