aboutsummaryrefslogtreecommitdiff
path: root/src/crmain.cc
diff options
context:
space:
mode:
authorfusion32 <marcopuzziello@gmail.com>2025-06-07 01:44:53 -0300
committerfusion32 <marcopuzziello@gmail.com>2025-06-07 01:46:11 -0300
commitbd145c3ebfc082286486a8700b9ce20bfd7383e2 (patch)
tree754b5c8bb1d5fb209e30dc78f698fc835ddf8cdb /src/crmain.cc
parent76f6ecb7c809c6e93447efb91bdf50f2a9d50d6b (diff)
downloadgame-bd145c3ebfc082286486a8700b9ce20bfd7383e2.tar.gz
game-bd145c3ebfc082286486a8700b9ce20bfd7383e2.zip
implement TFindCreatures and KillStatistics
Diffstat (limited to 'src/crmain.cc')
-rw-r--r--src/crmain.cc145
1 files changed, 142 insertions, 3 deletions
diff --git a/src/crmain.cc b/src/crmain.cc
index 49348d8..6a9602d 100644
--- a/src/crmain.cc
+++ b/src/crmain.cc
@@ -18,6 +18,99 @@ static TCreature *HashList[1000];
static matrix<uint32> *FirstChainCreature;
static vector<TCreature*> CreatureList(0, 10000, 1000);
+// TFindCreatures
+// =============================================================================
+TFindCreatures::TFindCreatures(int RadiusX, int RadiusY, int CenterX, int CenterY, int Mask){
+ this->initSearch(RadiusX, RadiusY, CenterX, CenterY, Mask);
+}
+
+TFindCreatures::TFindCreatures(int RadiusX, int RadiusY, uint32 CreatureID, int Mask){
+ TCreature *Creature = GetCreature(CreatureID);
+ if(Creature == NULL){
+ error("TFindCreatures::TFindCreatures: Kreatur existiert nicht.\n");
+ this->finished = true;
+ return;
+ }
+
+ this->initSearch(RadiusX, RadiusY, Creature->posx, Creature->posy, Mask);
+ this->SkipID = Creature->ID;
+}
+
+TFindCreatures::TFindCreatures(int RadiusX, int RadiusY, Object Obj, int Mask){
+ if(!Obj.exists()){
+ error("TFindCreatures::TFindCreatures: Übergebenes Objekt existiert nicht.\n");
+ this->finished = true;
+ return;
+ }
+
+ int ObjX, ObjY, ObjZ;
+ GetObjectCoordinates(Obj, &ObjX, &ObjY, &ObjZ);
+ this->initSearch(RadiusX, RadiusY, ObjX, ObjY, Mask);
+}
+
+void TFindCreatures::initSearch(int RadiusX, int RadiusY, int CenterX, int CenterY, int Mask){
+ this->startx = CenterX - RadiusX;
+ this->starty = CenterY - RadiusY;
+ this->endx = CenterX + RadiusX;
+ this->endy = CenterY + RadiusY;
+ // NOTE(fusion): See `TFindCreatures::getNext` for an explanation on the -1.
+ this->blockx = (this->startx / 16) - 1;
+ this->blocky = (this->starty / 16);
+ this->ActID = 0;
+ this->SkipID = 0;
+ this->Mask = Mask;
+ this->finished = false;
+}
+
+uint32 TFindCreatures::getNext(void){
+ if(this->finished){
+ return 0;
+ }
+
+ int StartBlockX = this->startx / 16;
+ int EndBlockX = this->endx / 16;
+ int EndBlockY = this->endy / 16;
+ while(true){
+ while(this->ActID == 0){
+ this->blockx += 1;
+ if(this->blockx > EndBlockX){
+ this->blockx = StartBlockX;
+ this->blocky += 1;
+ if(this->blocky > EndBlockY){
+ this->finished = true;
+ return 0;
+ }
+ }
+
+ uint32 *FirstID = FirstChainCreature->boundedAt(this->blockx, this->blocky);
+ if(FirstID != NULL){
+ this->ActID = *FirstID;
+ }else{
+ this->ActID = 0;
+ }
+ }
+
+ TCreature *Creature = GetCreature(this->ActID);
+ if(Creature == NULL){
+ error("TFindCreatures::getNext: Kreatur existiert nicht.\n");
+ this->ActID = 0;
+ continue;
+ }
+
+ this->ActID = Creature->NextChainCreature;
+ if(Creature->ID == this->SkipID
+ || Creature->posx < this->startx || Creature->posx > this->endx
+ || Creature->posy < this->starty || Creature->posy > this->endy
+ || (Creature->Type == PLAYER && (this->Mask & 0x01) == 0)
+ || (Creature->Type == NPC && (this->Mask & 0x02) == 0)
+ || (Creature->Type == MONSTER && (this->Mask & 0x04) == 0)){
+ continue;
+ }
+
+ return Creature->ID;
+ }
+}
+
// TCreature
// =============================================================================
TCreature::TCreature(void) :
@@ -793,7 +886,7 @@ void TCreature::CreatureMoveStimulus(uint32 CreatureID, int Type){
}
// TODO(fusion): Find out what `Type` is here.
- if(Type != 2 // STIMULUS_TYPE??
+ if(Type != 2 // STIMULUS_TYPE_??
|| !this->LockToDo
|| this->ActToDo >= this->NrToDo
|| this->ToDoList.at(this->ActToDo)->Code != TDAttack){
@@ -1022,8 +1115,6 @@ void MoveCreatures(int Delay){
// Kill Statistics
// =============================================================================
-void InitKillStatistics(void);//TODO
-void ExitKillStatistics(void);//TODO
void AddKillStatistics(int AttackerRace, int DefenderRace){
// NOTE(fusion): I think the race name can be "human" only for players,
// which means we're probably tracking how many creatures are killed by
@@ -1040,6 +1131,54 @@ void AddKillStatistics(int AttackerRace, int DefenderRace){
}
}
+void WriteKillStatistics(void){
+ // TODO(fusion): Using the same names with local and global variables is
+ // trash. I'd personally have all globals with a `g_` prefix but I'm trying
+ // to not change the original code too much.
+
+ // TODO(fusion): The way we manage race names here is a disaster but could
+ // make sense if there is a constant `MAX_RACE_NAME` somewhere. I've also
+ // seen the length of 30 often used with name strings so it could also be
+ // a general constant `MAX_NAME`.
+
+ int NumberOfRaces = 0;
+ char *RaceNames = new char[MAX_RACES * 30];
+ int *KilledPlayers = new int[MAX_RACES];
+ int *KilledCreatures = new int[MAX_RACES];
+ for(int Race = 0; Race < MAX_RACES; Race += 1){
+ if(::KilledCreatures[Race] == 0 && ::KilledPlayers[Race] == 0){
+ continue;
+ }
+
+ char *Name = &RaceNames[NumberOfRaces * 30];
+ if(Race == 0){
+ strcpy(Name, "(fire/poison/energy)");
+ }else{
+ sprintf(Name, "%s %s", RaceData[Race].Article, RaceData[Race].Name);
+ // TODO(fusion): The original function had a call to `Plural` and
+ // `Capitals` but didn't seem to put the results back into `Name`.
+ }
+
+ KilledPlayers[NumberOfRaces] = ::KilledPlayers[Race];
+ KilledCreatures[NumberOfRaces] = ::KilledCreatures[Race];
+ NumberOfRaces += 1;
+ }
+
+ KillStatisticsOrder(NumberOfRaces, RaceNames, KilledPlayers, KilledCreatures);
+ InitKillStatistics();
+}
+
+void InitKillStatistics(void){
+ for(int i = 0; i < MAX_RACES; i += 1){
+ KilledCreatures[i] = 0;
+ KilledPlayers[i] = 0;
+ }
+}
+
+void ExitKillStatistics(void){
+ WriteKillStatistics();
+}
+
// Race
// =============================================================================
TRaceData::TRaceData(void) :