From cb9c9aae7cced30f03ea46f969cb98794c867c46 Mon Sep 17 00:00:00 2001 From: Matthew Cline Date: Sun, 10 Jul 2011 04:00:52 -0700 Subject: [PATCH] Deal with third flag group in creatures Added support for reading and writing the third creature flag group, t_creaturflags3 (the offest already exists in Memory.xml). So far I've only figured out three of the flags (out of an apparent 13): 1) announce_titan, which causes the creature to be announced as if it was a titan or FB which had just arrived. 2) scuttle, which causes the creature to be die like it had been killed in the game. That is, it leaves behind a corpse, and will generate unhappy thoughts in dwarves if approriate. 3) ghostly, for creatures which are the ghosts of dead dwarves. I updated creaturemanager to use scuttle for --kill, and added the action --erase to kill in the old way which doesn't leave a corpse or creatre unhappy thoughts. --- .../include/dfhack-c/modules/Creatures_C.h | 1 + library/include/dfhack/modules/Creatures.h | 36 +++++++++++++ library/modules/Creatures.cpp | 18 +++++++ library/modules/Creatures_C.cpp | 11 ++++ tools/playground/creaturemanager.cpp | 50 ++++++++++++++++++- 5 files changed, 114 insertions(+), 2 deletions(-) diff --git a/library/include/dfhack-c/modules/Creatures_C.h b/library/include/dfhack-c/modules/Creatures_C.h index b3bbcae81..2c9a1240d 100644 --- a/library/include/dfhack-c/modules/Creatures_C.h +++ b/library/include/dfhack-c/modules/Creatures_C.h @@ -54,6 +54,7 @@ DFHACK_EXPORT int32_t Creatures_GetDwarfCivId(DFHackObject* cPtr); DFHACK_EXPORT int Creatures_WriteLabors(DFHackObject* cPtr, const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS]); DFHACK_EXPORT int Creatures_WriteHappiness(DFHackObject* cPtr, const uint32_t index, const uint32_t happiness_value); DFHACK_EXPORT int Creatures_WriteFlags(DFHackObject* cPtr, const uint32_t index, const uint32_t flags1, const uint32_t flags2); +DFHACK_EXPORT int Creatures_WriteFlags3(DFHackObject* cPtr, const uint32_t index, const uint32_t flags1, const uint32_t flags2, const uint32_t flags3); DFHACK_EXPORT int Creatures_WriteSkills(DFHackObject* cPtr, const uint32_t index, const t_soul* soul); DFHACK_EXPORT int Creatures_WriteAttributes(DFHackObject* cPtr, const uint32_t index, const t_creature* creature); DFHACK_EXPORT int Creatures_WriteSex(DFHackObject* cPtr, const uint32_t index, const uint8_t sex); diff --git a/library/include/dfhack/modules/Creatures.h b/library/include/dfhack/modules/Creatures.h index 99f6fd9c3..d90d530b3 100644 --- a/library/include/dfhack/modules/Creatures.h +++ b/library/include/dfhack/modules/Creatures.h @@ -111,6 +111,40 @@ namespace DFHack } bits; }; + union t_creaturflags3 + { + uint32_t whole; /*!< Access all flags as a single 32bit number. */ + struct + { + unsigned int unk0 : 1; /*!< Is 1 for new and dead creatures, + periodicaly set to 0 for non-dead creatures. + */ + unsigned int unk1 : 1; /*!< Is 1 for new creatures, periodically set + to 0 for non-dead creatures. */ + unsigned int unk2 : 1; /*!< Is set to 1 every tick for non-dead + creatures. */ + unsigned int unk3 : 1; /*!< Is periodically set to 0 for non-dead + creatures. */ + unsigned int announce_titan : 1; /*!< Announces creature like an + FB or titan. */ + unsigned int unk5 : 1; + unsigned int unk6 : 1; + unsigned int unk7 : 1; + unsigned int unk8 : 1; /*!< Is set to 1 every tick for non-dead + creatures. */ + unsigned int unk9 : 1; /*!< Is set to 0 every tick for non-dead + creatures. */ + unsigned int scuttle : 1; /*!< Scuttle creature: causes creature + to be killed, leaving a behind corpse + and generating negative thoughts like + a real kill. */ + unsigned int unk11 : 1; + unsigned int ghostly : 1; /*!< Creature is a ghost. */ + + unsigned int unk13_31 : 19; + } bits; + }; + // FIXME: WTF IS THIS SHIT? /* struct t_labor @@ -261,6 +295,7 @@ namespace DFHack t_creaturflags1 flags1; t_creaturflags2 flags2; + t_creaturflags3 flags3; t_name name; @@ -335,6 +370,7 @@ namespace DFHack bool WriteLabors(const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS]); bool WriteHappiness(const uint32_t index, const uint32_t happinessValue); bool WriteFlags(const uint32_t index, const uint32_t flags1, const uint32_t flags2); + bool WriteFlags(const uint32_t index, const uint32_t flags1, const uint32_t flags2, uint32_t flags3); bool WriteSkills(const uint32_t index, const t_soul &soul); bool WriteAttributes(const uint32_t index, const t_creature &creature); bool WriteSex(const uint32_t index, const uint8_t sex); diff --git a/library/modules/Creatures.cpp b/library/modules/Creatures.cpp index 6f86855a6..7c4aa9a00 100644 --- a/library/modules/Creatures.cpp +++ b/library/modules/Creatures.cpp @@ -68,6 +68,7 @@ struct Creatures::Private int32_t civ_offset; uint32_t flags1_offset; uint32_t flags2_offset; + uint32_t flags3_offset; uint32_t name_offset; uint32_t sex_offset; uint32_t caste_offset; @@ -156,6 +157,7 @@ Creatures::Creatures(DFContextShared* _d) creatures.pos_offset = OG_creature->getOffset ("position"); creatures.flags1_offset = OG_creature->getOffset ("flags1"); creatures.flags2_offset = OG_creature->getOffset ("flags2"); + creatures.flags3_offset = OG_creature->getOffset ("flags3"); creatures.sex_offset = OG_creature->getOffset ("sex"); creatures.caste_offset = OG_creature->getOffset ("caste"); creatures.id_offset = OG_creature->getOffset ("id"); @@ -284,6 +286,7 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball) p->readWord (addr_cr + offs.caste_offset, furball.caste); p->readDWord (addr_cr + offs.flags1_offset, furball.flags1.whole); p->readDWord (addr_cr + offs.flags2_offset, furball.flags2.whole); + p->readDWord (addr_cr + offs.flags3_offset, furball.flags3.whole); // custom profession p->readSTLString(addr_cr + offs.custom_profession_offset, furball.custom_profession, sizeof(furball.custom_profession)); // profession @@ -491,6 +494,21 @@ bool Creatures::WriteFlags(const uint32_t index, return true; } +bool Creatures::WriteFlags(const uint32_t index, + const uint32_t flags1, + const uint32_t flags2, + const uint32_t flags3) +{ + if(!d->Started || !d->Ft_basic) return false; + + uint32_t temp = d->p_cre->at (index); + Process * p = d->owner; + p->writeDWord (temp + d->creatures.flags1_offset, flags1); + p->writeDWord (temp + d->creatures.flags2_offset, flags2); + p->writeDWord (temp + d->creatures.flags3_offset, flags3); + return true; +} + bool Creatures::WriteSkills(const uint32_t index, const t_soul &soul) { if(!d->Started || !d->Ft_soul) return false; diff --git a/library/modules/Creatures_C.cpp b/library/modules/Creatures_C.cpp index 719377e9d..21eec21ef 100644 --- a/library/modules/Creatures_C.cpp +++ b/library/modules/Creatures_C.cpp @@ -212,6 +212,17 @@ int Creatures_WriteFlags(DFHackObject* cPtr, const uint32_t index, const uint32_ return -1; } +int Creatures_WriteFlags3(DFHackObject* cPtr, const uint32_t index, const uint32_t flags1, const uint32_t flags2, const uint32_t flags3) +{ + if(cPtr != NULL) + { + return ((DFHack::Creatures*)cPtr)->WriteFlags(index, flags1, flags2, + flags3); + } + + return -1; +} + int Creatures_WriteSkills(DFHackObject* cPtr, const uint32_t index, const t_soul* soul) { if(cPtr != NULL && soul != NULL) diff --git a/tools/playground/creaturemanager.cpp b/tools/playground/creaturemanager.cpp index fc82ff41c..2f4efc95a 100644 --- a/tools/playground/creaturemanager.cpp +++ b/tools/playground/creaturemanager.cpp @@ -208,6 +208,7 @@ void usage(int argc, const char * argv[]) << " * diplomat: all diplomats" << endl << " * FB: all forgotten beasts" << endl << " * female: all female creatures" << endl + << " * ghost: all ghosts" << endl << " * male: all male creatures" << endl << " * merchants: all merchants (including pack animals)" << endl << " * neuter: all neuter creatuers" << endl @@ -238,7 +239,8 @@ void usage(int argc, const char * argv[]) << "-rh : Remove hauler labors (stone hauling, etc.) from creature" << endl // Disabling mood doesn't work as intented << "--setmood : Set mood to n (-1 = no mood, max=4, buggy!)" << endl - << "--kill : Kill creature(s) (may need to be called multiple times)" << endl + << "--kill : Kill creature(s) (leaves behind corpses)" << endl + << "--erase : Remove creature(s) from game without killing" << endl << "--tame : Tames animals, recruits intelligent creatures." << endl << "--slaugher : Mark a creature for slaughter, even sentients" << endl << "--butcher : Same as --slaugher" << endl @@ -520,6 +522,7 @@ void printCreature(DFHack::Context * DF, const DFHack::t_creature & creature, in { DFHack::t_creaturflags1 f1 = creature.flags1; DFHack::t_creaturflags2 f2 = creature.flags2; + DFHack::t_creaturflags3 f3 = creature.flags3; if(f1.bits.dead){cout << "Flag: dead" << endl; } if(f1.bits.had_mood){cout<TranslateName(creature.artifact_name,false); @@ -628,6 +638,7 @@ public: bool find_nonicks; bool find_nicks; bool forgotten_beast; + bool ghost; bool merchant; bool pregnant; bool tame; @@ -654,6 +665,7 @@ public: find_nonicks = false; find_nicks = false; forgotten_beast = false; + ghost = false; merchant = false; pregnant = false; sex = SEX_ANY; @@ -696,6 +708,8 @@ public: diplomat = true; else if (type == "Fb" || type == "Beast") forgotten_beast = true; + else if (type == "Ghost") + ghost = true; else if (type == "Merchant") merchant = true; else if (type == "Pregnant") @@ -735,6 +749,7 @@ public: const DFHack::t_creaturflags1 &f1 = creature.flags1; const DFHack::t_creaturflags2 &f2 = creature.flags2; + const DFHack::t_creaturflags3 &f3 = creature.flags3; if(f1.bits.dead && !showdead) return false; @@ -758,6 +773,8 @@ public: return false; if(forgotten_beast && !f2.bits.visitor_uninvited) return false; + if(ghost && !f3.bits.ghostly) + return false; if(merchant && !f1.bits.merchant) return false; if(pregnant && creature.pregnancy_timer == 0) @@ -790,6 +807,7 @@ int main (int argc, const char* argv[]) bool remove_military_skills = false; bool remove_labors = false; bool kill_creature = false; + bool erase_creature = false; bool revive_creature = false; bool make_hauler = false; bool remove_hauler = false; @@ -926,6 +944,12 @@ int main (int argc, const char* argv[]) showallflags = true; showdead = true; } + else if(arg_cur == "--erase") + { + erase_creature = true; + showallflags = true; + showdead = true; + } else if(arg_cur == "--revive") { revive_creature = true; @@ -1088,7 +1112,7 @@ int main (int argc, const char* argv[]) remove_skills || remove_civil_skills || remove_military_skills || remove_labors || add_labor || remove_labor || make_hauler || remove_hauler - || kill_creature + || kill_creature || erase_creature || revive_creature || set_happiness || set_mood @@ -1119,6 +1143,27 @@ int main (int argc, const char* argv[]) if(creature.has_default_soul) { if (kill_creature && !creature.flags1.bits.dead) + { + DFHack::t_creaturflags1 f1 = creature.flags1; + DFHack::t_creaturflags2 f2 = creature.flags2; + DFHack::t_creaturflags3 f3 = creature.flags3; + + f3.bits.scuttle = true; + + cout << "Writing flags..." << endl; + if (!Creatures->WriteFlags(creature_idx, f1.whole, + f2.whole, f3.whole)) + { + cout << "Error writing creature flags!" << endl; + } + // We want the flags to be shown after our + // modification, but they are not read back + creature.flags1 = f1; + creature.flags2 = f2; + creature.flags3 = f3; + } + + if (erase_creature && !creature.flags1.bits.dead) { /* [quote author=Eldrick Tobin link=topic=58809.msg2178545#msg2178545 date=1302638055] @@ -1185,6 +1230,7 @@ int main (int argc, const char* argv[]) creature.flags2 = f2; } + if (revive_creature && creature.flags1.bits.dead) { DFHack::t_creaturflags1 f1 = creature.flags1;