Secrets
09-19-2010, 05:51 AM
Here's a diff for it. HUGE thanks to Derision and Trevius for getting the packets figured out. This implements two database fields, which the SQL is listed below for as well.
destructable - this enables the object as being destructable
destructablestr - this is the object string that gets placed as an object. The only way to use this is if the client you are viewing it on has that eqg file, and if that client has that eqg file in its assets list. This is named qeynos_assets.txt for example, and contains a list of the object eqgs that contain the destructable object. The filename is what you put in destructablestr.
TODO: Make objects appear differently depending on a flag you set in the object itself. This is outlined in the diff comments and just requires a database field. This is so objects don't sink in the ground, or are too high above the ground.
TODO2: Add the object unknown opcode to perl.
NOTE: Objects' destructable appearance state depends on the appearance. This is outlined in the diff comments if you are curious about it.
SQL
ALTER TABLE `npc_types` ADD COLUMN `destructable` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '' AFTER
`unique_spawn_by_name`, ADD COLUMN `destructablestr` varchar(24) NOT NULL DEFAULT '' COMMENT '' AFTER `destructable`
Diff
Index: common/emu_oplist.h
================================================== =================
--- common/emu_oplist.h (revision 1666)
+++ common/emu_oplist.h (working copy)
@@ -477,6 +477,7 @@
N(OP_TradeBusy),
N(OP_GuildUpdateURLAndChannel),
N(OP_CameraEffect),
+N(OP_DestructableRelated),
N(OP_SpellEffect),
N(OP_DzQuit),
N(OP_DzListTimers),
Index: common/eq_packet_structs.h
================================================== =================
--- common/eq_packet_structs.h (revision 1666)
+++ common/eq_packet_structs.h (working copy)
@@ -313,6 +313,25 @@
/*0348*/ Color_Struct colors[MAX_MATERIALS]; // Array elements correspond to struct equipment_colors above
};
/*0384*/ uint8 lfg; // 0=off, 1=lfg on
+ bool DestructableObject;
+ char DestructableString1[64];
+ char DestructableString2[64];
+ char DestructableString3[64];
+ uint32 DestructableUnk1;
+ uint32 DestructableUnk2;
+ uint32 DestructableID1;
+ uint32 DestructableID2;
+ uint32 DestructableID3;
+ uint32 DestructableID4;
+ uint32 DestructableUnk3;
+ uint32 DestructableUnk4;
+ uint32 DestructableUnk5;
+ uint32 DestructableUnk6;
+ uint32 DestructableUnk7;
+ uint32 DestructableUnk8;
+ uint32 DestructableUnk9;
+ uint8 DestructableByte;
+
/*0385*/
};
Index: common/patches/SoD.cpp
================================================== =================
--- common/patches/SoD.cpp (revision 1666)
+++ common/patches/SoD.cpp (working copy)
@@ -924,6 +924,29 @@
dest->FastQueuePacket(&in, ack_req);
}
+const char LiveTent[] =
+{
+0x61, 0x5f, 0x4d, 0x69, 0x6e, 0x6f, 0x68, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x65, 0x6e, 0x74, 0x30,
+0x37, 0x00, 0xdb, 0x3b, 0x00, 0x00, 0x28, 0x00, 0x00, 0x20, 0x41, 0x01, 0x00, 0x00, 0x60, 0x1d,
+0xd1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x45, 0x53, 0x54, 0x5f, 0x54, 0x4e,
+0x54, 0x5f, 0x47, 0x00, 0x61, 0x5f, 0x74, 0x65, 0x6e, 0x74, 0x00, 0x5a, 0x6f, 0x6e, 0x65, 0x41,
+0x63, 0x74, 0x6f, 0x72, 0x5f, 0x30, 0x31, 0x31, 0x38, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24,
+0x02, 0x00, 0x00, 0xb0, 0x07, 0x00, 0x00, 0xb1, 0x07, 0x00, 0x00, 0xb2, 0x07, 0x00, 0x00, 0xb3,
+0x07, 0x00, 0x00, 0x00, 0x9d, 0xf7, 0x13, 0x00, 0x00, 0x00, 0x00, 0x58, 0x9d, 0xf7, 0x13, 0x00,
+0x5b, 0xc5, 0x13, 0x60, 0x88, 0x12, 0x00, 0x66, 0x8f, 0x5a, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0x08, 0x00,
+0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+0x00, 0x00, 0x3e, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe1, 0x07, 0x00, 0x27, 0x83, 0x3a, 0x02, 0xf7, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
ENCODE(OP_ZoneEntry){ ENCODE_FORWARD(OP_ZoneSpawns); }
ENCODE(OP_ZoneSpawns) {
@@ -967,7 +990,15 @@
if(strlen(emu->suffix))
PacketSize += strlen(emu->suffix) + 1;
-
+
+ if(emu->DestructableObject)
+ {
+ PacketSize = PacketSize - 4; // No bodytype
+ PacketSize += 53; // Fixed portion
+ PacketSize += strlen(emu->DestructableString1) + 1;
+ PacketSize += strlen(emu->DestructableString2) + 1;
+ PacketSize += strlen(emu->DestructableString3) + 1;
+ }
bool ShowName = 1;
if(emu->bodytype >= 66)
{
@@ -1000,7 +1031,15 @@
VARSTRUCT_ENCODE_STRING(Buffer, emu->name);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->spawnId);
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->level);
- VARSTRUCT_ENCODE_TYPE(float, Buffer, SpawnSize - 0.7); // Eye Height?
+ if(emu->DestructableObject)
+ {
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x41200000);
+ }
+ else
+ {
+ VARSTRUCT_ENCODE_TYPE(float, Buffer, SpawnSize - 0.7); // Eye Height?
+ }
+
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC);
structs::Spawn_Struct_Bitfields *Bitfields = (structs::Spawn_Struct_Bitfields*)Buffer;
@@ -1023,6 +1062,12 @@
Bitfields->showname = ShowName;
+ if(emu->DestructableObject)
+ {
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x1d600000);
+ Buffer = Buffer -4;
+ }
+
Bitfields->ispet = emu->is_pet;
Buffer += sizeof(structs::Spawn_Struct_Bitfields);
@@ -1035,10 +1080,48 @@
if(strlen(emu->suffix))
OtherData = OtherData | 0x08;
+ if(emu->DestructableObject)
+ OtherData = OtherData | 0xd1;
+
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, OtherData);
- VARSTRUCT_ENCODE_TYPE(float, Buffer, -1); // unknown3
+ if(emu->DestructableObject)
+ {
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x00000000);
+ }
+ else
+ {
+ VARSTRUCT_ENCODE_TYPE(float, Buffer, -1); // unknown3
+ }
VARSTRUCT_ENCODE_TYPE(float, Buffer, 0); // unknown4
+
+ if(emu->DestructableObject)
+ {
+ // Live has 0xe1 for OtherData
+ //
+ VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructableString1);
+ VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructableString2);
+ VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructableString3);
+
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableUnk1);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableUnk2);
+
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableID1);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableID2);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableID3);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableID4);
+
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableUnk3);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableUnk4);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableUnk5);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableUnk6);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableUnk7);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableUnk8);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableUnk9);
+
+ VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->DestructableByte);
+ }
+
VARSTRUCT_ENCODE_TYPE(float, Buffer, emu->size);
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->face);
VARSTRUCT_ENCODE_TYPE(float, Buffer, emu->walkspeed);
@@ -1056,8 +1139,16 @@
// Setting this next field to zero will cause a crash. Looking at ShowEQ, if it is zero, the bodytype field is not
// present. Will sort that out later.
- VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 1); // This is a properties count field
- VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->bodytype);
+
+ if(!emu->DestructableObject)
+ {
+ VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 1); // This is a properties count field
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->bodytype);
+ }
+ else
+ {
+ VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0);
+ }
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->curHp);
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->haircolor);
@@ -1115,6 +1206,17 @@
Position->z = emu->z;
Position->deltaZ = emu->deltaZ;
+ if(emu->DestructableObject)
+ {
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x00000000);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x00000000);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x0007e1c3);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x023a8327);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x000002f7);
+
+ Buffer = Buffer -20;
+ }
+
Buffer += sizeof(structs::Spawn_Struct_Position);
if((emu->NPC == 0) || (emu->race <=12) || (emu->race == 128) || (emu ->race == 130) || (emu->race == 330) || (emu->race == 522))
@@ -1165,8 +1267,6 @@
}
Buffer += 33; // Unknown;
- //_log(NET__ERROR, "Sending zone spawn for %s", emu->name);
- //_hex(NET__ERROR, outapp->pBuffer, outapp->size);
dest->FastQueuePacket(&outapp, ack_req);
}
Index: zone/beacon.cpp
================================================== =================
--- zone/beacon.cpp (revision 1666)
+++ zone/beacon.cpp (working copy)
@@ -45,7 +45,7 @@
:Mob
(
NULL, NULL, 0, 0, 0, INVISIBLE_MAN, 0, BT_NoTarget, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,""
),
remove_timer(lifetime),
spell_timer(0)
Index: zone/client.cpp
================================================== =================
--- zone/client.cpp (revision 1666)
+++ zone/client.cpp (working copy)
@@ -139,7 +139,9 @@
0, // qglobal
0, // slow_mitigation
0, // maxlevel
- 0 // scalerate
+ 0, // scalerate
+ 0, //destructableobject
+ "" //destructableobjectstr
),
//these must be listed in the order they appear in client.h
Index: zone/command.cpp
================================================== =================
--- zone/command.cpp (revision 1666)
+++ zone/command.cpp (working copy)
@@ -860,6 +860,35 @@
void command_optest(Client *c, const Seperator *sep)
{
+ if(!c->GetTarget())
+ return;
+
+ EQApplicationPacket *outapp = new EQApplicationPacket(OP_DestructableRelated, 8);
+ char *Buffer = (char *)outapp->pBuffer;
+
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, c->GetTarget()->GetID());
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, atoi(sep->arg[1]));
+
+ /*
+ * EQApplicationPacket *outapp = new EQApplicationPacket(OP_TestBuff, 28);
+ char *Buffer = (char *)outapp->pBuffer;
+
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x00000039); // Effect type
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, c->GetTarget()->GetID());
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, c->GetTarget()->GetID());
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x00001388);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x00000000);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x00000bb8);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x04990101);
+ */
+
+ DumpPacket(outapp);
+ c->QueuePacket(outapp);
+ safe_delete(outapp);
+ return;
+
+
+
if(sep->IsNumber(1))
{
switch(atoi(sep->arg[1]))
Index: zone/mob.cpp
================================================== =================
--- zone/mob.cpp (revision 1666)
+++ zone/mob.cpp (working copy)
@@ -104,7 +104,9 @@
int8 in_qglobal,
float in_slow_mitigation, // Allows for mobs to mitigate how much they are slowed.
int8 in_maxlevel,
- int32 in_scalerate
+ int32 in_scalerate,
+ bool in_destructableobject,
+ const char * in_destructableobjectstr
) :
attack_timer(2000),
attack_dw_timer(2000),
@@ -371,6 +373,11 @@
nimbus_effect3 = 0;
flymode = FlyMode3;
+
+ destructableobject = in_destructableobject;
+
+ if(in_destructableobjectstr)
+ strncpy(destructableobjectstr,in_destructableobjec tstr,24);
// Pathing
PathingLOSState = UnknownLOS;
PathingLoopCount = 0;
@@ -818,7 +826,71 @@
}
memset(ns->spawn.set_to_0xFF, 0xFF, sizeof(ns->spawn.set_to_0xFF));
+ if(IsNPC() && destructableobject)
+ {
+ ns->spawn.DestructableObject = true;
+ // Changing the first string made it vanish, so it has some significance.
+ if(destructableobjectstr)
+ sprintf(ns->spawn.DestructableString1, destructableobjectstr);
+ // Changing the second string made no visible difference
+ sprintf(ns->spawn.DestructableString2, "%s", ns->spawn.name);
+ // Putting a string in the final one that was previously empty had no visible effect.
+ sprintf(ns->spawn.DestructableString3, "");
+ // Unk1 is 0x00000000 for zombie catapult
+ // Changing it to 0x0000ffff made it invisvible / untargetable
+ // 0x00000001 Visible
+ // 0x00000005 not visible
+ // 0x00000004 not visible
+ // 0x00000002 visible, but only one of two endpieces showing and crosspiece at an odd angle
+ // Maybe this corresponds to the state set with the #appearance commands.
+ ns->spawn.DestructableUnk1 = 0x00000000; // Was 0x00000000
+ // Next one was originally 0x000001f5;
+ // Changing it to 0x00000000 made it look like a human
+ // Changing it to 0x000001f0 made it look like a catapult
+ // Changing it to 0x000001e0 made it look like a catapult
+ // Changing it to 0x00000100 made it look like a catapult
+ // Changing it to 0x00000001 made it look like a catapult
+ ns->spawn.DestructableUnk2 = 0x00000224;
+ // These next 4 are mostly always sequential
+ // Originally they were 633, 634, 635, 636
+ // Changing them all to 633 - no visible effect.
+ // Changing them all to 636 - no visible effect.
+ // #appearance 44 1 makes it jump but no visible damage
+ // #appearance 44 2 makes it look completely broken but still visible
+ // #appearnace 44 3 makes it jump but not visible difference to 3
+ // #appearance 44 4 makes it disappear altogether
+ // #appearance 44 5 makes the client sad.
+ //
+ // Reversing the order of these four numbers and then using #appearance gain had no visible change.
+ //
+ // There is an opcode 0x301d live, 0x5ea1 SoD that seems to change whether the object is targetable or not.
+ //
+ // Setting these four ids to zero had no visible effect when the catapult spawned, nor when #appearance was used.
+ ns->spawn.DestructableID1 = 1968;
+ ns->spawn.DestructableID2 = 1969;
+ ns->spawn.DestructableID3 = 1970;
+ ns->spawn.DestructableID4 = 1971;
+ // Next one was originally 0x1ce45008, changing it to 0x00000000 made no visible difference
+ ns->spawn.DestructableUnk3 = 0x13f79d00;
+ // Next one was originally 0x1a68fe30, changing it to 0x00000000 made no visible difference
+ ns->spawn.DestructableUnk4 = 0x00000000;
+ // Next one was already 0x00000000
+ ns->spawn.DestructableUnk5 = 0x13f79d58;
+ // Next one was originally 0x005a69ec, changing it to 0x00000000 made no visible difference.
+ ns->spawn.DestructableUnk6 = 0x13c55b00;
+ // Next one was originally 0x1a68fe30, changing it to 0x00000000 made no visible difference.
+ ns->spawn.DestructableUnk7 = 0x00128860;
+ // Next one was originally 0x0059de6d, changing it to 0x00000000 made no visible difference.
+ ns->spawn.DestructableUnk8 = 0x005a8f66;
+ // Next one was originally 0x00000201, changing it to 0x00000000 made no visible difference.
+ // For the Minohten tents, 0x00000000 had them up in the air, whil 0x201 put them on the ground.
+ // Changing it it 0x00000001 makes the tent sink into the ground.
+ ns->spawn.DestructableUnk9 = 0x00000201; // Needs to be 201 for tents
+ ns->spawn.DestructableByte = 0x00;
+
+ ns->spawn.flymode = 0;
+ }
}
void Mob::CreateDespawnPacket(EQApplicationPacket* app, bool Decay)
Index: zone/mob.h
================================================== =================
--- zone/mob.h (revision 1666)
+++ zone/mob.h (working copy)
@@ -425,7 +425,9 @@
int8 in_qglobal,
float in_slow_mitigation, // Allows for mobs to mitigate how much they are slowed.
int8 in_maxlevel,
- int32 in_scalerate
+ int32 in_scalerate,
+ bool in_destructableobject,
+ const char* in_destructableobjectstr
);
virtual ~Mob();
@@ -1302,6 +1304,10 @@
bool m_hasPartialSpellRune;
bool m_hasDeathSaveChance;
int flymode;
+
+ bool destructableobject;
+ char destructableobjectstr[24];
+
int QGVarDuration(const char *fmt);
void InsertQuestGlobal(int charid, int npcid, int zoneid, const char *name, const char *value, int expdate);
Index: zone/npc.cpp
================================================== =================
--- zone/npc.cpp (revision 1666)
+++ zone/npc.cpp (working copy)
@@ -109,7 +109,9 @@
d->qglobal,
d->slow_mitigation,
d->maxlevel,
- d->scalerate ),
+ d->scalerate ,
+ d->destructable,
+ d->destructablestr),
attacked_timer(CombatEventTimer_expire),
swarm_timer(100),
classattack_timer(1000),
@@ -343,6 +345,8 @@
ldon_trap_detected = 0;
}
qGlobals = NULL;
+ destructableobject = d->destructable;
+ strcpy(destructableobjectstr, d->destructablestr);
guard_x_saved = 0;
guard_y_saved = 0;
guard_z_saved = 0;
Index: zone/npc.h
================================================== =================
--- zone/npc.h (revision 1666)
+++ zone/npc.h (working copy)
@@ -306,6 +306,8 @@
uint32 GetAdventureTemplate() const { return adventure_template_id; }
+ bool IsDestuctableObject() { return destructableobject; }
+
protected:
const NPCType* NPCTypedata;
Index: zone/PlayerCorpse.cpp
================================================== =================
--- zone/PlayerCorpse.cpp (revision 1666)
+++ zone/PlayerCorpse.cpp (working copy)
@@ -198,7 +198,7 @@
in_npc->GetHeading(),in_npc->GetX(),in_npc->GetY(),in_npc->GetZ(),0,
in_npc->GetTexture(),in_npc->GetHelmTexture(),
0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0xff,0,0,0,0,0,0,0,0,0,0),
+ 0,0,0,0,0,0,0,0,0,0,0,0xff,0,0,0,0,0,0,0,0,0,0,0,""),
corpse_decay_timer(in_decaytime),
corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)),
corpse_graveyard_timer(0),
@@ -303,7 +303,9 @@
0, // qglobal
0, // slow_mitigation
0, // maxlevel
- 0 // scalerate
+ 0, // scalerate
+ 0, //destr obj
+ "" //destr obj
),
corpse_decay_timer(RuleI(Character, CorpseDecayTimeMS)),
corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)),
@@ -413,7 +415,7 @@
: Mob("Unnamed_Corpse","",0,0,in_gender, in_race, in_class, BT_Humanoid, in_deity, in_level,0, in_size, 0, in_heading, in_x, in_y, in_z,0,in_texture,in_helmtexture,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0xff,
- 0,0,0,0,0,0,0,0,0,0),
+ 0,0,0,0,0,0,0,0,0,0,0,""),
corpse_decay_timer(RuleI(Character, CorpseDecayTimeMS)),
corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)),
corpse_graveyard_timer(RuleI(Zone, GraveyardTimeMS)),
Index: zone/zonedb.cpp
================================================== =================
--- zone/zonedb.cpp (revision 1666)
+++ zone/zonedb.cpp (working copy)
@@ -1095,7 +1095,9 @@
"npc_types.maxlevel,"
"npc_types.scalerate,"
"npc_types.private_corpse,"
- "npc_types.unique_spawn_by_name";
+ "npc_types.unique_spawn_by_name,"
+ "npc_types.destructable,"
+ "npc_types.destructablestr";
MakeAnyLenString(&query, "%s FROM npc_types WHERE id=%d", basic_query, id);
@@ -1265,6 +1267,8 @@
tmpNPCType->scalerate = atoi(row[r++]);
tmpNPCType->private_corpse = atoi(row[r++]) == 1 ? true : false;
tmpNPCType->unique_spawn_by_name = atoi(row[r++]) == 1 ? true : false;
+ tmpNPCType->destructable = atoi(row[r++]) == 1 ? true : false;
+ strncpy(tmpNPCType->destructablestr, row[r++], 24);
// If NPC with duplicate NPC id already in table,
// free item we attempted to add.
Index: zone/zonedump.h
================================================== =================
--- zone/zonedump.h (revision 1666)
+++ zone/zonedump.h (working copy)
@@ -117,6 +117,8 @@
int32 scalerate;
bool private_corpse;
bool unique_spawn_by_name;
+ bool destructable;
+ char destructablestr[24];
};
struct ZSDump_Spawn2 {
destructable - this enables the object as being destructable
destructablestr - this is the object string that gets placed as an object. The only way to use this is if the client you are viewing it on has that eqg file, and if that client has that eqg file in its assets list. This is named qeynos_assets.txt for example, and contains a list of the object eqgs that contain the destructable object. The filename is what you put in destructablestr.
TODO: Make objects appear differently depending on a flag you set in the object itself. This is outlined in the diff comments and just requires a database field. This is so objects don't sink in the ground, or are too high above the ground.
TODO2: Add the object unknown opcode to perl.
NOTE: Objects' destructable appearance state depends on the appearance. This is outlined in the diff comments if you are curious about it.
SQL
ALTER TABLE `npc_types` ADD COLUMN `destructable` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '' AFTER
`unique_spawn_by_name`, ADD COLUMN `destructablestr` varchar(24) NOT NULL DEFAULT '' COMMENT '' AFTER `destructable`
Diff
Index: common/emu_oplist.h
================================================== =================
--- common/emu_oplist.h (revision 1666)
+++ common/emu_oplist.h (working copy)
@@ -477,6 +477,7 @@
N(OP_TradeBusy),
N(OP_GuildUpdateURLAndChannel),
N(OP_CameraEffect),
+N(OP_DestructableRelated),
N(OP_SpellEffect),
N(OP_DzQuit),
N(OP_DzListTimers),
Index: common/eq_packet_structs.h
================================================== =================
--- common/eq_packet_structs.h (revision 1666)
+++ common/eq_packet_structs.h (working copy)
@@ -313,6 +313,25 @@
/*0348*/ Color_Struct colors[MAX_MATERIALS]; // Array elements correspond to struct equipment_colors above
};
/*0384*/ uint8 lfg; // 0=off, 1=lfg on
+ bool DestructableObject;
+ char DestructableString1[64];
+ char DestructableString2[64];
+ char DestructableString3[64];
+ uint32 DestructableUnk1;
+ uint32 DestructableUnk2;
+ uint32 DestructableID1;
+ uint32 DestructableID2;
+ uint32 DestructableID3;
+ uint32 DestructableID4;
+ uint32 DestructableUnk3;
+ uint32 DestructableUnk4;
+ uint32 DestructableUnk5;
+ uint32 DestructableUnk6;
+ uint32 DestructableUnk7;
+ uint32 DestructableUnk8;
+ uint32 DestructableUnk9;
+ uint8 DestructableByte;
+
/*0385*/
};
Index: common/patches/SoD.cpp
================================================== =================
--- common/patches/SoD.cpp (revision 1666)
+++ common/patches/SoD.cpp (working copy)
@@ -924,6 +924,29 @@
dest->FastQueuePacket(&in, ack_req);
}
+const char LiveTent[] =
+{
+0x61, 0x5f, 0x4d, 0x69, 0x6e, 0x6f, 0x68, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x65, 0x6e, 0x74, 0x30,
+0x37, 0x00, 0xdb, 0x3b, 0x00, 0x00, 0x28, 0x00, 0x00, 0x20, 0x41, 0x01, 0x00, 0x00, 0x60, 0x1d,
+0xd1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x45, 0x53, 0x54, 0x5f, 0x54, 0x4e,
+0x54, 0x5f, 0x47, 0x00, 0x61, 0x5f, 0x74, 0x65, 0x6e, 0x74, 0x00, 0x5a, 0x6f, 0x6e, 0x65, 0x41,
+0x63, 0x74, 0x6f, 0x72, 0x5f, 0x30, 0x31, 0x31, 0x38, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24,
+0x02, 0x00, 0x00, 0xb0, 0x07, 0x00, 0x00, 0xb1, 0x07, 0x00, 0x00, 0xb2, 0x07, 0x00, 0x00, 0xb3,
+0x07, 0x00, 0x00, 0x00, 0x9d, 0xf7, 0x13, 0x00, 0x00, 0x00, 0x00, 0x58, 0x9d, 0xf7, 0x13, 0x00,
+0x5b, 0xc5, 0x13, 0x60, 0x88, 0x12, 0x00, 0x66, 0x8f, 0x5a, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0x08, 0x00,
+0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+0x00, 0x00, 0x3e, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe1, 0x07, 0x00, 0x27, 0x83, 0x3a, 0x02, 0xf7, 0x02,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
ENCODE(OP_ZoneEntry){ ENCODE_FORWARD(OP_ZoneSpawns); }
ENCODE(OP_ZoneSpawns) {
@@ -967,7 +990,15 @@
if(strlen(emu->suffix))
PacketSize += strlen(emu->suffix) + 1;
-
+
+ if(emu->DestructableObject)
+ {
+ PacketSize = PacketSize - 4; // No bodytype
+ PacketSize += 53; // Fixed portion
+ PacketSize += strlen(emu->DestructableString1) + 1;
+ PacketSize += strlen(emu->DestructableString2) + 1;
+ PacketSize += strlen(emu->DestructableString3) + 1;
+ }
bool ShowName = 1;
if(emu->bodytype >= 66)
{
@@ -1000,7 +1031,15 @@
VARSTRUCT_ENCODE_STRING(Buffer, emu->name);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->spawnId);
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->level);
- VARSTRUCT_ENCODE_TYPE(float, Buffer, SpawnSize - 0.7); // Eye Height?
+ if(emu->DestructableObject)
+ {
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x41200000);
+ }
+ else
+ {
+ VARSTRUCT_ENCODE_TYPE(float, Buffer, SpawnSize - 0.7); // Eye Height?
+ }
+
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC);
structs::Spawn_Struct_Bitfields *Bitfields = (structs::Spawn_Struct_Bitfields*)Buffer;
@@ -1023,6 +1062,12 @@
Bitfields->showname = ShowName;
+ if(emu->DestructableObject)
+ {
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x1d600000);
+ Buffer = Buffer -4;
+ }
+
Bitfields->ispet = emu->is_pet;
Buffer += sizeof(structs::Spawn_Struct_Bitfields);
@@ -1035,10 +1080,48 @@
if(strlen(emu->suffix))
OtherData = OtherData | 0x08;
+ if(emu->DestructableObject)
+ OtherData = OtherData | 0xd1;
+
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, OtherData);
- VARSTRUCT_ENCODE_TYPE(float, Buffer, -1); // unknown3
+ if(emu->DestructableObject)
+ {
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x00000000);
+ }
+ else
+ {
+ VARSTRUCT_ENCODE_TYPE(float, Buffer, -1); // unknown3
+ }
VARSTRUCT_ENCODE_TYPE(float, Buffer, 0); // unknown4
+
+ if(emu->DestructableObject)
+ {
+ // Live has 0xe1 for OtherData
+ //
+ VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructableString1);
+ VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructableString2);
+ VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructableString3);
+
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableUnk1);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableUnk2);
+
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableID1);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableID2);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableID3);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableID4);
+
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableUnk3);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableUnk4);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableUnk5);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableUnk6);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableUnk7);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableUnk8);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructableUnk9);
+
+ VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->DestructableByte);
+ }
+
VARSTRUCT_ENCODE_TYPE(float, Buffer, emu->size);
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->face);
VARSTRUCT_ENCODE_TYPE(float, Buffer, emu->walkspeed);
@@ -1056,8 +1139,16 @@
// Setting this next field to zero will cause a crash. Looking at ShowEQ, if it is zero, the bodytype field is not
// present. Will sort that out later.
- VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 1); // This is a properties count field
- VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->bodytype);
+
+ if(!emu->DestructableObject)
+ {
+ VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 1); // This is a properties count field
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->bodytype);
+ }
+ else
+ {
+ VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0);
+ }
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->curHp);
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->haircolor);
@@ -1115,6 +1206,17 @@
Position->z = emu->z;
Position->deltaZ = emu->deltaZ;
+ if(emu->DestructableObject)
+ {
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x00000000);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x00000000);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x0007e1c3);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x023a8327);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x000002f7);
+
+ Buffer = Buffer -20;
+ }
+
Buffer += sizeof(structs::Spawn_Struct_Position);
if((emu->NPC == 0) || (emu->race <=12) || (emu->race == 128) || (emu ->race == 130) || (emu->race == 330) || (emu->race == 522))
@@ -1165,8 +1267,6 @@
}
Buffer += 33; // Unknown;
- //_log(NET__ERROR, "Sending zone spawn for %s", emu->name);
- //_hex(NET__ERROR, outapp->pBuffer, outapp->size);
dest->FastQueuePacket(&outapp, ack_req);
}
Index: zone/beacon.cpp
================================================== =================
--- zone/beacon.cpp (revision 1666)
+++ zone/beacon.cpp (working copy)
@@ -45,7 +45,7 @@
:Mob
(
NULL, NULL, 0, 0, 0, INVISIBLE_MAN, 0, BT_NoTarget, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,""
),
remove_timer(lifetime),
spell_timer(0)
Index: zone/client.cpp
================================================== =================
--- zone/client.cpp (revision 1666)
+++ zone/client.cpp (working copy)
@@ -139,7 +139,9 @@
0, // qglobal
0, // slow_mitigation
0, // maxlevel
- 0 // scalerate
+ 0, // scalerate
+ 0, //destructableobject
+ "" //destructableobjectstr
),
//these must be listed in the order they appear in client.h
Index: zone/command.cpp
================================================== =================
--- zone/command.cpp (revision 1666)
+++ zone/command.cpp (working copy)
@@ -860,6 +860,35 @@
void command_optest(Client *c, const Seperator *sep)
{
+ if(!c->GetTarget())
+ return;
+
+ EQApplicationPacket *outapp = new EQApplicationPacket(OP_DestructableRelated, 8);
+ char *Buffer = (char *)outapp->pBuffer;
+
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, c->GetTarget()->GetID());
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, atoi(sep->arg[1]));
+
+ /*
+ * EQApplicationPacket *outapp = new EQApplicationPacket(OP_TestBuff, 28);
+ char *Buffer = (char *)outapp->pBuffer;
+
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x00000039); // Effect type
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, c->GetTarget()->GetID());
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, c->GetTarget()->GetID());
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x00001388);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x00000000);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x00000bb8);
+ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x04990101);
+ */
+
+ DumpPacket(outapp);
+ c->QueuePacket(outapp);
+ safe_delete(outapp);
+ return;
+
+
+
if(sep->IsNumber(1))
{
switch(atoi(sep->arg[1]))
Index: zone/mob.cpp
================================================== =================
--- zone/mob.cpp (revision 1666)
+++ zone/mob.cpp (working copy)
@@ -104,7 +104,9 @@
int8 in_qglobal,
float in_slow_mitigation, // Allows for mobs to mitigate how much they are slowed.
int8 in_maxlevel,
- int32 in_scalerate
+ int32 in_scalerate,
+ bool in_destructableobject,
+ const char * in_destructableobjectstr
) :
attack_timer(2000),
attack_dw_timer(2000),
@@ -371,6 +373,11 @@
nimbus_effect3 = 0;
flymode = FlyMode3;
+
+ destructableobject = in_destructableobject;
+
+ if(in_destructableobjectstr)
+ strncpy(destructableobjectstr,in_destructableobjec tstr,24);
// Pathing
PathingLOSState = UnknownLOS;
PathingLoopCount = 0;
@@ -818,7 +826,71 @@
}
memset(ns->spawn.set_to_0xFF, 0xFF, sizeof(ns->spawn.set_to_0xFF));
+ if(IsNPC() && destructableobject)
+ {
+ ns->spawn.DestructableObject = true;
+ // Changing the first string made it vanish, so it has some significance.
+ if(destructableobjectstr)
+ sprintf(ns->spawn.DestructableString1, destructableobjectstr);
+ // Changing the second string made no visible difference
+ sprintf(ns->spawn.DestructableString2, "%s", ns->spawn.name);
+ // Putting a string in the final one that was previously empty had no visible effect.
+ sprintf(ns->spawn.DestructableString3, "");
+ // Unk1 is 0x00000000 for zombie catapult
+ // Changing it to 0x0000ffff made it invisvible / untargetable
+ // 0x00000001 Visible
+ // 0x00000005 not visible
+ // 0x00000004 not visible
+ // 0x00000002 visible, but only one of two endpieces showing and crosspiece at an odd angle
+ // Maybe this corresponds to the state set with the #appearance commands.
+ ns->spawn.DestructableUnk1 = 0x00000000; // Was 0x00000000
+ // Next one was originally 0x000001f5;
+ // Changing it to 0x00000000 made it look like a human
+ // Changing it to 0x000001f0 made it look like a catapult
+ // Changing it to 0x000001e0 made it look like a catapult
+ // Changing it to 0x00000100 made it look like a catapult
+ // Changing it to 0x00000001 made it look like a catapult
+ ns->spawn.DestructableUnk2 = 0x00000224;
+ // These next 4 are mostly always sequential
+ // Originally they were 633, 634, 635, 636
+ // Changing them all to 633 - no visible effect.
+ // Changing them all to 636 - no visible effect.
+ // #appearance 44 1 makes it jump but no visible damage
+ // #appearance 44 2 makes it look completely broken but still visible
+ // #appearnace 44 3 makes it jump but not visible difference to 3
+ // #appearance 44 4 makes it disappear altogether
+ // #appearance 44 5 makes the client sad.
+ //
+ // Reversing the order of these four numbers and then using #appearance gain had no visible change.
+ //
+ // There is an opcode 0x301d live, 0x5ea1 SoD that seems to change whether the object is targetable or not.
+ //
+ // Setting these four ids to zero had no visible effect when the catapult spawned, nor when #appearance was used.
+ ns->spawn.DestructableID1 = 1968;
+ ns->spawn.DestructableID2 = 1969;
+ ns->spawn.DestructableID3 = 1970;
+ ns->spawn.DestructableID4 = 1971;
+ // Next one was originally 0x1ce45008, changing it to 0x00000000 made no visible difference
+ ns->spawn.DestructableUnk3 = 0x13f79d00;
+ // Next one was originally 0x1a68fe30, changing it to 0x00000000 made no visible difference
+ ns->spawn.DestructableUnk4 = 0x00000000;
+ // Next one was already 0x00000000
+ ns->spawn.DestructableUnk5 = 0x13f79d58;
+ // Next one was originally 0x005a69ec, changing it to 0x00000000 made no visible difference.
+ ns->spawn.DestructableUnk6 = 0x13c55b00;
+ // Next one was originally 0x1a68fe30, changing it to 0x00000000 made no visible difference.
+ ns->spawn.DestructableUnk7 = 0x00128860;
+ // Next one was originally 0x0059de6d, changing it to 0x00000000 made no visible difference.
+ ns->spawn.DestructableUnk8 = 0x005a8f66;
+ // Next one was originally 0x00000201, changing it to 0x00000000 made no visible difference.
+ // For the Minohten tents, 0x00000000 had them up in the air, whil 0x201 put them on the ground.
+ // Changing it it 0x00000001 makes the tent sink into the ground.
+ ns->spawn.DestructableUnk9 = 0x00000201; // Needs to be 201 for tents
+ ns->spawn.DestructableByte = 0x00;
+
+ ns->spawn.flymode = 0;
+ }
}
void Mob::CreateDespawnPacket(EQApplicationPacket* app, bool Decay)
Index: zone/mob.h
================================================== =================
--- zone/mob.h (revision 1666)
+++ zone/mob.h (working copy)
@@ -425,7 +425,9 @@
int8 in_qglobal,
float in_slow_mitigation, // Allows for mobs to mitigate how much they are slowed.
int8 in_maxlevel,
- int32 in_scalerate
+ int32 in_scalerate,
+ bool in_destructableobject,
+ const char* in_destructableobjectstr
);
virtual ~Mob();
@@ -1302,6 +1304,10 @@
bool m_hasPartialSpellRune;
bool m_hasDeathSaveChance;
int flymode;
+
+ bool destructableobject;
+ char destructableobjectstr[24];
+
int QGVarDuration(const char *fmt);
void InsertQuestGlobal(int charid, int npcid, int zoneid, const char *name, const char *value, int expdate);
Index: zone/npc.cpp
================================================== =================
--- zone/npc.cpp (revision 1666)
+++ zone/npc.cpp (working copy)
@@ -109,7 +109,9 @@
d->qglobal,
d->slow_mitigation,
d->maxlevel,
- d->scalerate ),
+ d->scalerate ,
+ d->destructable,
+ d->destructablestr),
attacked_timer(CombatEventTimer_expire),
swarm_timer(100),
classattack_timer(1000),
@@ -343,6 +345,8 @@
ldon_trap_detected = 0;
}
qGlobals = NULL;
+ destructableobject = d->destructable;
+ strcpy(destructableobjectstr, d->destructablestr);
guard_x_saved = 0;
guard_y_saved = 0;
guard_z_saved = 0;
Index: zone/npc.h
================================================== =================
--- zone/npc.h (revision 1666)
+++ zone/npc.h (working copy)
@@ -306,6 +306,8 @@
uint32 GetAdventureTemplate() const { return adventure_template_id; }
+ bool IsDestuctableObject() { return destructableobject; }
+
protected:
const NPCType* NPCTypedata;
Index: zone/PlayerCorpse.cpp
================================================== =================
--- zone/PlayerCorpse.cpp (revision 1666)
+++ zone/PlayerCorpse.cpp (working copy)
@@ -198,7 +198,7 @@
in_npc->GetHeading(),in_npc->GetX(),in_npc->GetY(),in_npc->GetZ(),0,
in_npc->GetTexture(),in_npc->GetHelmTexture(),
0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0xff,0,0,0,0,0,0,0,0,0,0),
+ 0,0,0,0,0,0,0,0,0,0,0,0xff,0,0,0,0,0,0,0,0,0,0,0,""),
corpse_decay_timer(in_decaytime),
corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)),
corpse_graveyard_timer(0),
@@ -303,7 +303,9 @@
0, // qglobal
0, // slow_mitigation
0, // maxlevel
- 0 // scalerate
+ 0, // scalerate
+ 0, //destr obj
+ "" //destr obj
),
corpse_decay_timer(RuleI(Character, CorpseDecayTimeMS)),
corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)),
@@ -413,7 +415,7 @@
: Mob("Unnamed_Corpse","",0,0,in_gender, in_race, in_class, BT_Humanoid, in_deity, in_level,0, in_size, 0, in_heading, in_x, in_y, in_z,0,in_texture,in_helmtexture,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0xff,
- 0,0,0,0,0,0,0,0,0,0),
+ 0,0,0,0,0,0,0,0,0,0,0,""),
corpse_decay_timer(RuleI(Character, CorpseDecayTimeMS)),
corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)),
corpse_graveyard_timer(RuleI(Zone, GraveyardTimeMS)),
Index: zone/zonedb.cpp
================================================== =================
--- zone/zonedb.cpp (revision 1666)
+++ zone/zonedb.cpp (working copy)
@@ -1095,7 +1095,9 @@
"npc_types.maxlevel,"
"npc_types.scalerate,"
"npc_types.private_corpse,"
- "npc_types.unique_spawn_by_name";
+ "npc_types.unique_spawn_by_name,"
+ "npc_types.destructable,"
+ "npc_types.destructablestr";
MakeAnyLenString(&query, "%s FROM npc_types WHERE id=%d", basic_query, id);
@@ -1265,6 +1267,8 @@
tmpNPCType->scalerate = atoi(row[r++]);
tmpNPCType->private_corpse = atoi(row[r++]) == 1 ? true : false;
tmpNPCType->unique_spawn_by_name = atoi(row[r++]) == 1 ? true : false;
+ tmpNPCType->destructable = atoi(row[r++]) == 1 ? true : false;
+ strncpy(tmpNPCType->destructablestr, row[r++], 24);
// If NPC with duplicate NPC id already in table,
// free item we attempted to add.
Index: zone/zonedump.h
================================================== =================
--- zone/zonedump.h (revision 1666)
+++ zone/zonedump.h (working copy)
@@ -117,6 +117,8 @@
int32 scalerate;
bool private_corpse;
bool unique_spawn_by_name;
+ bool destructable;
+ char destructablestr[24];
};
struct ZSDump_Spawn2 {