Go Back   EQEmulator Home > EQEmulator Forums > Development > Development::Development

Development::Development Forum for development topics and for those interested in EQEMu development. (Not a support forum)

 
 
Thread Tools Display Modes
Prev Previous Post   Next Post Next
  #1  
Old 08-29-2007, 11:58 PM
cbodmer
Fire Beetle
 
Join Date: Oct 2006
Posts: 24
Default LDoN Open Button Support

Background:
With LDoN a special type of treasure chest was introduced, which players could "open" by clicking on the Open pushbutton. Most everyone should be familiar with this type of object.

Technically, chests are nothing other than a special type of NPC, having a spawnpoint and loot like any other mob. Opening a chest is instantly killing this mob, causing it to play its death animation (ie chest cracking open).

I've gone ahead and implemented an initial version of this functionality. It's still vs 1030, but it should be no problem to apply to a later version, since it's mostly one line additions. Since I only have a Titanium client to test with, I've only updated the Titanium Client opcode list so this will NOT work out of the box for any other clients.

Patches:
common/classes.h
Code:
--- ../EQEmu-0.7.0-1030/common/classes.h	2006-05-13 04:35:58.000000000 +0200
+++ ../EQEmu/common/classes.h	2007-08-30 10:36:40.000000000 +0200
@@ -58,6 +58,7 @@
 #define ADVENTURERECRUITER 60
 #define ADVENTUREMERCHANT 61
 #define CORPSE_CLASS 62	//only seen on Danvi's Corpse in Akheva so far..
+#define LDON_TREASURE 62 // LDON Treasure Chests, Barrels, etc.
 #define TRIBUTE_MASTER	63
 #define GUILD_TRIBUTE_MASTER	64	//not sure
 #define warrior_1 1
common/emu_oplist.h
Code:
--- ../EQEmu-0.7.0-1030/common/emu_oplist.h	2007-08-05 23:13:12.000000000 +0200
+++ ../EQEmu/common/emu_oplist.h	2007-08-30 00:30:46.000000000 +0200
@@ -355,6 +355,7 @@
 N(OP_ReclaimCrystals),
 N(OP_Report),
 N(OP_SenseHeading),
+N(OP_LDoNOpen),
 N(OP_DynamicWall),
 N(OP_RequestTitles),
 N(OP_PurchaseLeadershipAA),
common/opcode_dispatch.h
Code:
--- ../EQEmu-0.7.0-1030/common/opcode_dispatch.h	2007-07-22 22:54:32.000000000 +0200
+++ ../EQEmu/common/opcode_dispatch.h	2007-08-30 00:28:06.000000000 +0200
@@ -129,6 +129,7 @@
 INz(OP_FeignDeath);	//?
 INz(OP_Sneak);		//?
 INz(OP_Hide);		//?
+INz(OP_LDoNOpen);
 INv(OP_ChannelMessage, ChannelMessage_Struct);
 IN(OP_WearChange, WearChange_Struct);
 IN(OP_DeleteSpawn, EntityId_Struct);	//client->server follows OP_SaveOnZoneReq
People with access to other clients should try and see if they can find the "Open" Opcode for their client and update the config files accordingly.

utils/patch_Titanium.conf
Code:
--- ../EQEmu-0.7.0-1030/utils/patch_Titanium.conf	2007-08-05 23:13:12.000000000 +0200
+++ ../patch_Titanium.conf	2007-08-30 13:34:44.000000000 +0200
@@ -398,6 +398,7 @@
 OP_Sneak=0x74e1			
 OP_Fishing=0x0b36
 OP_InstillDoubt=0x389e		#intimidation
+OP_LDoNOpen=0x083b	# CB: open LDoN chest 08/30/07
 
 #Task packets
 OP_CompletedTasks=0x76a2			# ShowEQ 10/27/05
zone/aggro.cpp
Code:
--- ../EQEmu-0.7.0-1030/zone/aggro.cpp	2007-07-17 03:03:48.000000000 +0200
+++ ../EQEmu/zone/aggro.cpp	2007-08-30 11:26:44.000000000 +0200
@@ -455,7 +455,10 @@
 	// solar: the format here is a matrix of mob type vs mob type.
 	// redundant ones are omitted and the reverse is tried if it falls through.
 
-	
+	// cb: LDoN Treasure chests dont fight
+	if(this->GetClass() == LDON_TREASURE && this->GetBodyType() == BT_Boxes)
+		return(false);
+
 	// first figure out if we're pets.  we always look at the master's flags.
 	// no need to compare pets to anything
 	mob1 = our_owner ? our_owner : this;
The follow patch looks huge; all it really does is prevent players from getting
EXP for their chest "kills". I did some code reformatting, that is why there's so many changes.

zone/attack.cpp
Code:
--- ../EQEmu-0.7.0-1030/zone/attack.cpp	2007-08-11 08:14:57.000000000 +0200
+++ ../EQEmu/zone/attack.cpp	2007-08-30 11:47:45.000000000 +0200
@@ -1102,11 +1102,13 @@
 
 			char tmp[20];
 			database.GetVariable("ServerType", tmp, 9);
-			if(atoi(tmp)==1 && other != NULL && other->IsClient()){
+			if(atoi(tmp)==1 && other != NULL && other->IsClient())
+			{
 				char tmp2[10] = {0};
 				database.GetVariable("PvPreward", tmp, 9);
 				int reward = atoi(tmp);
-				if(reward==3){
+				if(reward==3)
+				{
 					database.GetVariable("PvPitem", tmp2, 9);
 					int pvpitem = atoi(tmp2);
 					if(pvpitem>0 && pvpitem<200000)
@@ -1118,11 +1120,15 @@
 					new_corpse->SetPKItem(1);
 				else
 					new_corpse->SetPKItem(0);
-				if(other->CastToClient()->isgrouped) {
+				if(other->CastToClient()->isgrouped) 
+				{
 					Group* group = entity_list.GetGroupByClient(other->CastToClient());
-					if(group != 0) {
-						for(int i=0;i<6;i++) {
-							if(group->members[i] != NULL) {
+					if(group != 0) 
+					{
+						for(int i=0;i<6;i++) 
+						{
+							if(group->members[i] != NULL) 
+							{
 								new_corpse->AllowMobLoot(group->members[i],i);
 							}
 						}
@@ -1490,7 +1496,6 @@
 
 	safe_delete(app);
 	
-	
 	Mob *give_exp = hate_list.GetDamageTop(this);
 	if(give_exp == NULL)
 		give_exp = killer;
@@ -1501,30 +1506,36 @@
 	if(give_exp && give_exp->IsClient())
 		give_exp_client = give_exp->CastToClient();
 	
-    if (give_exp_client && !IsCorpse() && MerchantType == 0)
+	if(!(this->GetClass() == LDON_TREASURE && this->GetBodyType() == BT_Boxes))
 	{
-		Group *kg = entity_list.GetGroupByClient(give_exp_client);
-		if (give_exp_client->IsGrouped() && kg != NULL)
+		// cb: if we're not a LDON treasure chest, we give XP
+	
+	  if (give_exp_client && !IsCorpse() && MerchantType == 0)
 		{
-			if(give_exp_client->GetAdventureID()>0){
-				AdventureInfo AF = database.GetAdventureInfo(give_exp_client->GetAdventureID());
-				if(zone->GetZoneID() == AF.zonedungeonid && AF.type==ADVENTURE_MASSKILL)
-					give_exp_client->SendAdventureUpdate();
-				else if(zone->GetZoneID() == AF.zonedungeonid && AF.type==ADVENTURE_NAMED && (AF.Objetive==GetNPCTypeID() || AF.ObjetiveValue==GetNPCTypeID()))
-					give_exp_client->SendAdventureFinish(1, AF.points,true);
+			Group *kg = entity_list.GetGroupByClient(give_exp_client);
+			if (give_exp_client->IsGrouped() && kg != NULL)
+			{
+				if(give_exp_client->GetAdventureID()>0){
+					AdventureInfo AF = database.GetAdventureInfo(give_exp_client->GetAdventureID());
+					if(zone->GetZoneID() == AF.zonedungeonid && AF.type==ADVENTURE_MASSKILL)
+						give_exp_client->SendAdventureUpdate();
+					else if(zone->GetZoneID() == AF.zonedungeonid && AF.type==ADVENTURE_NAMED && (AF.Objetive==GetNPCTypeID() || AF.ObjetiveValue==GetNPCTypeID()))
+						give_exp_client->SendAdventureFinish(1, AF.points,true);
+				}
+				kg->SplitExp((EXP_FORMULA), this);
+			}
+			else
+	    {
+	     	int conlevel = give_exp->GetLevelCon(GetLevel());
+	      if (conlevel != CON_GREEN)
+	      {
+				    give_exp_client->AddEXP((EXP_FORMULA), conlevel); // Pyro: Comment this if NPC death crashes zone
+	      }
 			}
-			kg->SplitExp((EXP_FORMULA), this);
-		}
-		else
-        {
-        	int conlevel = give_exp->GetLevelCon(GetLevel());
-            if (conlevel != CON_GREEN)
-            {
-			    give_exp_client->AddEXP((EXP_FORMULA), conlevel); // Pyro: Comment this if NPC death crashes zone
-            }
 		}
 	}
 	
+	
 	//do faction hits even if we are a merchant, so long as a player killed us
 	if(give_exp_client)
 		hate_list.DoFactionHits(GetNPCFactionID());
zone/client_packet.cpp
Code:
--- ../EQEmu-0.7.0-1030/zone/client_packet.h	2007-07-21 22:39:54.000000000 +0200
+++ ../EQEmu/zone/client_packet.h	2007-08-30 00:41:01.000000000 +0200
@@ -57,6 +57,7 @@
 	void Handle_OP_Camp(const EQApplicationPacket *app);
 	void Handle_OP_Logout(const EQApplicationPacket *app);
 	void Handle_OP_SenseHeading(const EQApplicationPacket *app);
+	void Handle_OP_LDoNOpen(const EQApplicationPacket *app);
 	void Handle_OP_FeignDeath(const EQApplicationPacket *app);
 	void Handle_OP_Sneak(const EQApplicationPacket *app);
 	void Handle_OP_Hide(const EQApplicationPacket *app);
zone/client_packet.cpp
Code:
--- ../EQEmu-0.7.0-1030/zone/client_packet.cpp	2007-08-05 23:13:12.000000000 +0200
+++ ../EQEmu/zone/client_packet.cpp	2007-08-30 11:27:13.000000000 +0200
@@ -157,6 +157,7 @@
 	ConnectedOpcodes[OP_Camp] = &Client::Handle_OP_Camp;
 	ConnectedOpcodes[OP_Logout] = &Client::Handle_OP_Logout;
 //	ConnectedOpcodes[OP_SenseHeading] = &Client::Handle_OP_SenseHeading;
+  ConnectedOpcodes[OP_LDoNOpen] = &Client::Handle_OP_LDoNOpen;
 	ConnectedOpcodes[OP_FeignDeath] = &Client::Handle_OP_FeignDeath;
 	ConnectedOpcodes[OP_Sneak] = &Client::Handle_OP_Sneak;
 	ConnectedOpcodes[OP_Hide] = &Client::Handle_OP_Hide;
@@ -2312,6 +2313,18 @@
 	return;
 }
 
+void Client::Handle_OP_LDoNOpen(const EQApplicationPacket *app)
+{
+	Mob * target = GetTarget();
+	if(target)
+	{
+		if(target->IsMob() && target->GetClass()==LDON_TREASURE && target->GetBodyType()==BT_Boxes)
+			target->Damage((Mob *)this, target->GetMaxHP()*2, SPELL_UNKNOWN, HAND_TO_HAND, false);
+		else
+		  cout << "Illegal target: OP_LDoNOpen expects mob class " << LDON_TREASURE << ", bodytype " << BT_Boxes << endl;
+	}
+}
+
 void Client::Handle_OP_Dye(const EQApplicationPacket *app)
 {
 	if(app->size!=sizeof(DyeStruct))
To test it, create a mob with any race/level, class=62 (LDON Chest) and bodytype=33 (BT_Boxes). I've included the bodytype criteria in order to make sure that there's very little chance of there being actual mobs with both class=62 and bodytype=33 in your databases.

Enjoy,
-Chris
 


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

   

All times are GMT -4. The time now is 10:49 PM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3