Browse Source

Tutorial instructions for the Far Journey zone
Standardized the message numbers and will send the correct one based on client version
Fixed /tell to not assume that both clients were the same version
Tons of quest fixes
Fixed various spawn bugs

LethalEncounter 3 years ago
parent
commit
ebddaba763
37 changed files with 1560 additions and 639 deletions
  1. 1 1
      EQ2/source/LoginServer/Login.vcxproj
  2. 1 1
      EQ2/source/WorldServer/Bots/BotCommands.cpp
  3. 2 2
      EQ2/source/WorldServer/Chat/ChatChannel.cpp
  4. 6 6
      EQ2/source/WorldServer/Combat.cpp
  5. 87 90
      EQ2/source/WorldServer/Commands/Commands.cpp
  6. 3 43
      EQ2/source/WorldServer/Commands/Commands.h
  7. 6 6
      EQ2/source/WorldServer/GroundSpawn.cpp
  8. 27 27
      EQ2/source/WorldServer/Guilds/Guild.cpp
  9. 17 3
      EQ2/source/WorldServer/Items/Items.cpp
  10. 1 2
      EQ2/source/WorldServer/Items/Items.h
  11. 505 48
      EQ2/source/WorldServer/LuaFunctions.cpp
  12. 28 0
      EQ2/source/WorldServer/LuaFunctions.h
  13. 80 7
      EQ2/source/WorldServer/LuaInterface.cpp
  14. 12 1
      EQ2/source/WorldServer/LuaInterface.h
  15. 4 4
      EQ2/source/WorldServer/NPC_AI.cpp
  16. 42 34
      EQ2/source/WorldServer/Player.cpp
  17. 74 3
      EQ2/source/WorldServer/Player.h
  18. 1 1
      EQ2/source/WorldServer/PlayerGroups.cpp
  19. 10 4
      EQ2/source/WorldServer/Quests.cpp
  20. 34 12
      EQ2/source/WorldServer/Spawn.cpp
  21. 4 4
      EQ2/source/WorldServer/SpellProcess.cpp
  22. 3 3
      EQ2/source/WorldServer/Tradeskills/Tradeskills.cpp
  23. 3 3
      EQ2/source/WorldServer/Transmute.cpp
  24. 6 41
      EQ2/source/WorldServer/World.cpp
  25. 1 1
      EQ2/source/WorldServer/WorldDatabase.cpp
  26. 434 118
      EQ2/source/WorldServer/client.cpp
  27. 8 4
      EQ2/source/WorldServer/client.h
  28. 42 54
      EQ2/source/WorldServer/zoneserver.cpp
  29. 1 1
      EQ2/source/WorldServer/zoneserver.h
  30. 1 1
      EQ2/source/common/ConfigReader.cpp
  31. 17 9
      EQ2/source/common/PacketStruct.cpp
  32. 2 1
      EQ2/win/EQ2WorldVC10.sln
  33. 3 2
      EQ2/win/VC10Projects/EQ2World.vcxproj
  34. 25 28
      server/Quests/PeatBog/Reinforcements.lua
  35. 50 63
      server/Quests/PeatBog/ambushed.lua
  36. 9 8
      server/SpawnStructs.xml
  37. 10 3
      server/WorldStructs.xml

+ 1 - 1
EQ2/source/LoginServer/Login.vcxproj

@@ -27,7 +27,7 @@
     <IncludePath>$(SolutionDir)..\source\depends\mariadb-10.1.19\include;$(SolutionDir)..\source\depends\zlib\include;$(SolutionDir)..\source\depends\recastnavigation\Detour\Include;$(SolutionDir)..\source\depends\boost_1_72_0\;$(SolutionDir)..\source\depends\glm\;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
     <IncludePath>$(SolutionDir)..\source\depends\mariadb-10.1.19\include;$(SolutionDir)..\source\depends\zlib\include;$(SolutionDir)..\source\depends\recastnavigation\Detour\Include;$(SolutionDir)..\source\depends\boost_1_72_0\;$(SolutionDir)..\source\depends\glm\;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
     <LibraryPath>$(SolutionDir)..\source\depends\recastnavigation\RecastDemo\Build\vs2019\lib\Debug;$(SolutionDir)..\source\depends\mariadb-10.1.19\lib\64-debug;$(SolutionDir)..\source\depends\zlib\lib;$(SolutionDir)..\source\depends\boost_1_72_0\lib64-msvc-14.2;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64</LibraryPath>
     <LibraryPath>$(SolutionDir)..\source\depends\recastnavigation\RecastDemo\Build\vs2019\lib\Debug;$(SolutionDir)..\source\depends\mariadb-10.1.19\lib\64-debug;$(SolutionDir)..\source\depends\zlib\lib;$(SolutionDir)..\source\depends\boost_1_72_0\lib64-msvc-14.2;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64</LibraryPath>
     <LinkIncremental>false</LinkIncremental>
     <LinkIncremental>false</LinkIncremental>
-    <OutDir>$(SolutionDir)loginserver\</OutDir>
+    <OutDir>E:\EQ2EMu\my_server\</OutDir>
     <IntDir>.\$(ProjectName)__Debug64\</IntDir>
     <IntDir>.\$(ProjectName)__Debug64\</IntDir>
     <TargetName>$(ProjectName)__Debug64</TargetName>
     <TargetName>$(ProjectName)__Debug64</TargetName>
   </PropertyGroup>
   </PropertyGroup>

+ 1 - 1
EQ2/source/WorldServer/Bots/BotCommands.cpp

@@ -591,7 +591,7 @@ void Commands::Command_Bot_Inv(Client* client, Seperator* sep) {
 				Item* item = bot->GetEquipmentList()->GetItem(i);
 				Item* item = bot->GetEquipmentList()->GetItem(i);
 				if (item) {
 				if (item) {
 					//\\aITEM %u %u:%s\\/a
 					//\\aITEM %u %u:%s\\/a
-					item_list += to_string(i) + ":\t\\aITEM " + to_string(item->details.item_id) + " " + to_string(item->details.unique_id) + ":" + item->name + "\\/a \n";
+					item_list += to_string(i) + ":\t" + item->CreateItemLink(GetVersion(), true) + "\n";
 				}
 				}
 			}
 			}
 
 

+ 2 - 2
EQ2/source/WorldServer/Chat/ChatChannel.cpp

@@ -142,7 +142,7 @@ bool ChatChannel::TellChannel(Client *client, const char *message, const char* n
 			packet_struct->setDataByName("from", name2);
 			packet_struct->setDataByName("from", name2);
 
 
 		packet_struct->setDataByName("to", to_client->GetPlayer()->GetName());
 		packet_struct->setDataByName("to", to_client->GetPlayer()->GetName());
-		packet_struct->setDataByName("channel", 34);
+		packet_struct->setDataByName("channel", to_client->GetMessageChannelColor(CHANNEL_CUSTOM_CHANNEL));
 		packet_struct->setDataByName("language", 0);
 		packet_struct->setDataByName("language", 0);
 		packet_struct->setDataByName("message", message);
 		packet_struct->setDataByName("message", message);
 		packet_struct->setDataByName("channel_name", name);
 		packet_struct->setDataByName("channel_name", name);
@@ -170,7 +170,7 @@ bool ChatChannel::TellChannelClient(Client* to_client, const char* message, cons
 		packet_struct->setDataByName("to_spawn_id", 0xFFFFFFFF);
 		packet_struct->setDataByName("to_spawn_id", 0xFFFFFFFF);
 		packet_struct->setDataByName("from", name2);
 		packet_struct->setDataByName("from", name2);
 		packet_struct->setDataByName("to", to_client->GetPlayer()->GetName());
 		packet_struct->setDataByName("to", to_client->GetPlayer()->GetName());
-		packet_struct->setDataByName("channel", 34);
+		packet_struct->setDataByName("channel", to_client->GetMessageChannelColor(CHANNEL_CUSTOM_CHANNEL));
 		packet_struct->setDataByName("language", 0);
 		packet_struct->setDataByName("language", 0);
 		packet_struct->setDataByName("message", message);
 		packet_struct->setDataByName("message", message);
 		packet_struct->setDataByName("channel_name", name);
 		packet_struct->setDataByName("channel_name", name);

+ 6 - 6
EQ2/source/WorldServer/Combat.cpp

@@ -156,14 +156,14 @@ bool Entity::AttackAllowed(Entity* target, float distance, bool range_attack) {
 			// Distance is less then min weapon range
 			// Distance is less then min weapon range
 			if(distance < weapon->ranged_info->range_low) {
 			if(distance < weapon->ranged_info->range_low) {
 				if (client)
 				if (client)
-					client->SimpleMessage(CHANNEL_COLOR_COMBAT, "Your target is too close! Move back!");
+					client->SimpleMessage(CHANNEL_GENERAL_COMBAT, "Your target is too close! Move back!");
 				LogWrite(COMBAT__DEBUG, 3, "AttackAllowed", "Failed to attack: range attack, target to close");
 				LogWrite(COMBAT__DEBUG, 3, "AttackAllowed", "Failed to attack: range attack, target to close");
 				return false;
 				return false;
 			}
 			}
 			// Distance is greater then max weapon range
 			// Distance is greater then max weapon range
 			if  (distance > (weapon->ranged_info->range_high + ammo->thrown_info->range)) {
 			if  (distance > (weapon->ranged_info->range_high + ammo->thrown_info->range)) {
 				if (client)
 				if (client)
-					client->SimpleMessage(CHANNEL_COLOR_COMBAT, "Your target is too far away! Move closer!");
+					client->SimpleMessage(CHANNEL_GENERAL_COMBAT, "Your target is too far away! Move closer!");
 				LogWrite(COMBAT__DEBUG, 3, "AttackAllowed", "Failed to attack: range attack, target is to far");
 				LogWrite(COMBAT__DEBUG, 3, "AttackAllowed", "Failed to attack: range attack, target is to far");
 				return false;
 				return false;
 			}
 			}
@@ -414,7 +414,7 @@ bool Entity::SpellAttack(Spawn* victim, float distance, LuaSpell* luaspell, int8
 				string success_message = spell->GetSpellData()->success_message;
 				string success_message = spell->GetSpellData()->success_message;
 				if(success_message.find("%t") < 0xFFFFFFFF)
 				if(success_message.find("%t") < 0xFFFFFFFF)
 					success_message.replace(success_message.find("%t"), 2, victim->GetName());
 					success_message.replace(success_message.find("%t"), 2, victim->GetName());
-				client->Message(CHANNEL_COLOR_SPELL, success_message.c_str());
+				client->Message(CHANNEL_YOU_CAST, success_message.c_str());
 				//commented out the following line as it was causing a duplicate message EmemJR 5/4/2019
 				//commented out the following line as it was causing a duplicate message EmemJR 5/4/2019
 				//GetZone()->SendDamagePacket(this, victim, DAMAGE_PACKET_TYPE_SPELL_DAMAGE, hit_result, damage_type, 0, spell->GetName()); 
 				//GetZone()->SendDamagePacket(this, victim, DAMAGE_PACKET_TYPE_SPELL_DAMAGE, hit_result, damage_type, 0, spell->GetName()); 
 			}
 			}
@@ -423,7 +423,7 @@ bool Entity::SpellAttack(Spawn* victim, float distance, LuaSpell* luaspell, int8
 			string effect_message = spell->GetSpellData()->effect_message;
 			string effect_message = spell->GetSpellData()->effect_message;
 			if(effect_message.find("%t") < 0xFFFFFFFF)
 			if(effect_message.find("%t") < 0xFFFFFFFF)
 				effect_message.replace(effect_message.find("%t"), 2, victim->GetName());
 				effect_message.replace(effect_message.find("%t"), 2, victim->GetName());
-			GetZone()->SimpleMessage(CHANNEL_COLOR_SPELL_EFFECT, effect_message.c_str(), victim, 50);
+			GetZone()->SimpleMessage(CHANNEL_SPELLS, effect_message.c_str(), victim, 50);
 		}
 		}
 	}
 	}
 	else {
 	else {
@@ -506,13 +506,13 @@ bool Entity::ProcAttack(Spawn* victim, int8 damage_type, int32 low_damage, int32
 			if(client) {
 			if(client) {
 				if(success_msg.find("%t") < 0xFFFFFFFF)
 				if(success_msg.find("%t") < 0xFFFFFFFF)
 					success_msg.replace(success_msg.find("%t"), 2, victim->GetName());
 					success_msg.replace(success_msg.find("%t"), 2, victim->GetName());
-				client->Message(CHANNEL_COLOR_SPELL, success_msg.c_str());
+				client->Message(CHANNEL_YOU_CAST, success_msg.c_str());
 			}
 			}
 		}
 		}
 		if (effect_msg.length() > 0) {
 		if (effect_msg.length() > 0) {
 			if(effect_msg.find("%t") < 0xFFFFFFFF)
 			if(effect_msg.find("%t") < 0xFFFFFFFF)
 				effect_msg.replace(effect_msg.find("%t"), 2, victim->GetName());
 				effect_msg.replace(effect_msg.find("%t"), 2, victim->GetName());
-			GetZone()->SimpleMessage(CHANNEL_COLOR_SPELL_EFFECT, effect_msg.c_str(), victim, 50);
+			GetZone()->SimpleMessage(CHANNEL_SPELLS, effect_msg.c_str(), victim, 50);
 		}
 		}
 	}
 	}
 	else {
 	else {

+ 87 - 90
EQ2/source/WorldServer/Commands/Commands.cpp

@@ -1425,7 +1425,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 						Recipe* recipe_book = new Recipe(master_recipebook_list.GetRecipeBooks(item->details.item_id));
 						Recipe* recipe_book = new Recipe(master_recipebook_list.GetRecipeBooks(item->details.item_id));
 						// if valid recipe book and the player doesn't have it
 						// if valid recipe book and the player doesn't have it
 						if (recipe_book && recipe_book->GetLevel() > client->GetPlayer()->GetTSLevel()) {
 						if (recipe_book && recipe_book->GetLevel() > client->GetPlayer()->GetTSLevel()) {
-							client->Message(CHANNEL_COLOR_WHITE, "Your tradeskill level is not high enough to scribe this book.");
+							client->Message(CHANNEL_NARRATIVE, "Your tradeskill level is not high enough to scribe this book.");
 							safe_delete(recipe_book);
 							safe_delete(recipe_book);
 						}
 						}
 						else if (recipe_book && !(client->GetPlayer()->GetRecipeBookList()->HasRecipeBook(item->details.item_id))) {
 						else if (recipe_book && !(client->GetPlayer()->GetRecipeBookList()->HasRecipeBook(item->details.item_id))) {
@@ -1456,7 +1456,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 									Recipe* recipe = new Recipe(master_recipe_list.GetRecipe((*itr)->GetID()));
 									Recipe* recipe = new Recipe(master_recipe_list.GetRecipe((*itr)->GetID()));
 									client->GetPlayer()->GetRecipeList()->AddRecipe(recipe);
 									client->GetPlayer()->GetRecipeList()->AddRecipe(recipe);
 									database.SavePlayerRecipe(client->GetPlayer(), recipe->GetID());
 									database.SavePlayerRecipe(client->GetPlayer(), recipe->GetID());
-									client->Message(CHANNEL_COLOR_WHITE, "Recipe: \"%s\" put in recipe book.", recipe->GetName());
+									client->Message(CHANNEL_NARRATIVE, "Recipe: \"%s\" put in recipe book.", recipe->GetName());
 
 
 									if (packet && client->GetRecipeListSent()) {
 									if (packet && client->GetRecipeListSent()) {
 										packet->setArrayDataByName("id", recipe->GetID(), i);
 										packet->setArrayDataByName("id", recipe->GetID(), i);
@@ -1487,7 +1487,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 						}
 						}
 						else {
 						else {
 							if (recipe_book)
 							if (recipe_book)
-								client->Message(CHANNEL_COLOR_WHITE, "You have already learned all you can from this item.");
+								client->Message(CHANNEL_NARRATIVE, "You have already learned all you can from this item.");
 							safe_delete(recipe_book);
 							safe_delete(recipe_book);
 						}
 						}
 						
 						
@@ -1665,7 +1665,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 						 }
 						 }
 		case COMMAND_TELL:{
 		case COMMAND_TELL:{
 			if(sep && sep->arg[0] && sep->argplus[1]){
 			if(sep && sep->arg[0] && sep->argplus[1]){
-				if(!zone_list.HandleGlobalChatMessage(client, sep->arg[0], CHANNEL_TELL, sep->argplus[1]))
+				if(!zone_list.HandleGlobalChatMessage(client, sep->arg[0], CHANNEL_PRIVATE_TELL, sep->argplus[1]))
 					client->Message(CHANNEL_COLOR_RED,"Unable to find client %s",sep->arg[0]);
 					client->Message(CHANNEL_COLOR_RED,"Unable to find client %s",sep->arg[0]);
 			}else
 			}else
 				client->SimpleMessage(CHANNEL_COLOR_YELLOW,"Usage:  /tell {character_name} {message}");
 				client->SimpleMessage(CHANNEL_COLOR_YELLOW,"Usage:  /tell {character_name} {message}");
@@ -1688,7 +1688,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 		case COMMAND_OOC:{
 		case COMMAND_OOC:{
 			//For now ooc will be the global chat channel, eventually when we create more channels we will create a global chat channel
 			//For now ooc will be the global chat channel, eventually when we create more channels we will create a global chat channel
 			if(sep && sep->arg[0][0])
 			if(sep && sep->arg[0][0])
-				zone_list.HandleGlobalChatMessage(client, 0, CHANNEL_OOC, sep->argplus[0]);
+				zone_list.HandleGlobalChatMessage(client, 0, CHANNEL_OUT_OF_CHARACTER, sep->argplus[0]);
 			else
 			else
 				client->SimpleMessage(CHANNEL_COLOR_YELLOW,"Usage:  /ooc {message}");
 				client->SimpleMessage(CHANNEL_COLOR_YELLOW,"Usage:  /ooc {message}");
 			break;
 			break;
@@ -2277,7 +2277,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 					world.GetGroupManager()->GroupMessage(group_id, "%s has left the group.", client->GetPlayer()->GetName());
 					world.GetGroupManager()->GroupMessage(group_id, "%s has left the group.", client->GetPlayer()->GetName());
 				}
 				}
 
 
-				client->SimpleMessage(CHANNEL_COLOR_GROUP, "You have left the group");
+				client->SimpleMessage(CHANNEL_GROUP_CHAT, "You have left the group");
 			}
 			}
 
 
 			break;
 			break;
@@ -2396,10 +2396,10 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 			if(send_kicked_message)
 			if(send_kicked_message)
 				world.GetGroupManager()->GroupMessage(group_id, "%s was kicked from the group.", kicked->GetName());
 				world.GetGroupManager()->GroupMessage(group_id, "%s was kicked from the group.", kicked->GetName());
 			else
 			else
-				client->Message(CHANNEL_COLOR_GROUP, "You kicked %s from the group", kicked->GetName());
+				client->Message(CHANNEL_GROUP_CHAT, "You kicked %s from the group", kicked->GetName());
 
 
 			if (kicked_client)
 			if (kicked_client)
-				kicked_client->SimpleMessage(CHANNEL_COLOR_GROUP, "You were kicked from the group");
+				kicked_client->SimpleMessage(CHANNEL_GROUP_CHAT, "You were kicked from the group");
 				
 				
 			break;
 			break;
 		}
 		}
@@ -2432,13 +2432,13 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 				int8 result = world.GetGroupManager()->AcceptInvite(client->GetPlayer());
 				int8 result = world.GetGroupManager()->AcceptInvite(client->GetPlayer());
 
 
 				if (result == 0)
 				if (result == 0)
-					client->SimpleMessage(CHANNEL_GROUP, "You have joined the group.");
+					client->SimpleMessage(CHANNEL_GROUP_CHAT, "You have joined the group.");
 				else if (result == 1)
 				else if (result == 1)
-					client->SimpleMessage(CHANNEL_GROUP, "You do not have a pending invite.");
+					client->SimpleMessage(CHANNEL_GROUP_CHAT, "You do not have a pending invite.");
 				else if (result == 2)
 				else if (result == 2)
-					client->SimpleMessage(CHANNEL_GROUP, "Unable to join group - could not find leader.");
+					client->SimpleMessage(CHANNEL_GROUP_CHAT, "Unable to join group - could not find leader.");
 				else
 				else
-					client->SimpleMessage(CHANNEL_GROUP, "Unable to join group - unknown error.");
+					client->SimpleMessage(CHANNEL_GROUP_CHAT, "Unable to join group - unknown error.");
 			}
 			}
 			break;
 			break;
 		}
 		}
@@ -2984,7 +2984,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 			}
 			}
 			if(type == 0){
 			if(type == 0){
 				if(incombat)
 				if(incombat)
-					client->SimpleMessage(CHANNEL_COLOR_COMBAT, "You stop fighting.");
+					client->SimpleMessage(CHANNEL_GENERAL_COMBAT, "You stop fighting.");
 				player->InCombat(false);
 				player->InCombat(false);
 				player->InCombat(false, true);
 				player->InCombat(false, true);
 				player->SetRangeAttack(false);
 				player->SetRangeAttack(false);
@@ -2995,12 +2995,12 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 					if(incombat && player->GetRangeAttack()){
 					if(incombat && player->GetRangeAttack()){
 						player->SetRangeAttack(false);
 						player->SetRangeAttack(false);
 						player->InCombat(false, true);
 						player->InCombat(false, true);
-						client->SimpleMessage(CHANNEL_COLOR_COMBAT, "You stop fighting.");
+						client->SimpleMessage(CHANNEL_GENERAL_COMBAT, "You stop fighting.");
 					}
 					}
 					else{
 					else{
 						player->SetRangeAttack(true);
 						player->SetRangeAttack(true);
 						player->InCombat(true, true);
 						player->InCombat(true, true);
-						client->SimpleMessage(CHANNEL_COLOR_COMBAT, "You start fighting.");
+						client->SimpleMessage(CHANNEL_GENERAL_COMBAT, "You start fighting.");
 					}
 					}
 				}
 				}
 				else {
 				else {
@@ -3008,7 +3008,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 					player->SetRangeAttack(false);
 					player->SetRangeAttack(false);
 					player->InCombat(true);
 					player->InCombat(true);
 					if(!incombat)
 					if(!incombat)
-						client->SimpleMessage(CHANNEL_COLOR_COMBAT, "You start fighting.");
+						client->SimpleMessage(CHANNEL_GENERAL_COMBAT, "You start fighting.");
 				}
 				}
 				/*else
 				/*else
 					client->SimpleMessage(CHANNEL_COLOR_YELLOW, "You cannot attack that!");*/
 					client->SimpleMessage(CHANNEL_COLOR_YELLOW, "You cannot attack that!");*/
@@ -3050,6 +3050,8 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 				int8 quantity = atoi(sep->arg[1]);
 				int8 quantity = atoi(sep->arg[1]);
 				client->BuyItem(item_id, quantity);
 				client->BuyItem(item_id, quantity);
 			}
 			}
+			else
+				Command_SendMerchantWindow(client, sep);
 			break;
 			break;
 								  }
 								  }
 		case COMMAND_MERCHANT_SELL:{
 		case COMMAND_MERCHANT_SELL:{
@@ -3151,9 +3153,33 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 				client->AcceptQuestReward(quest, item_id);
 				client->AcceptQuestReward(quest, item_id);
 				break;
 				break;
 			}
 			}
-
+			bool collectedItems = false;
 			if (collection = player->GetPendingCollectionReward())
 			if (collection = player->GetPendingCollectionReward())
 				client->AcceptCollectionRewards(collection, selectable_item_id);
 				client->AcceptCollectionRewards(collection, selectable_item_id);
+			else if (client->GetPlayer()->HasPendingItemRewards()) {
+				vector<Item*> items = client->GetPlayer()->GetPendingItemRewards();
+				if (items.size() > 0) {
+					collectedItems = true;
+					for (int i = 0; i < items.size(); i++) {
+						client->GetPlayer()->AddItem(new Item(items[i]));
+					}
+					client->GetPlayer()->ClearPendingItemRewards();
+				}
+				map<int32, Item*> selectable_item = client->GetPlayer()->GetPendingSelectableItemReward(item_id);
+				if (selectable_item.size() > 0) {
+					collectedItems = true;
+					map<int32, Item*>::iterator itr;
+					for (itr = selectable_item.begin(); itr != selectable_item.end(); itr++) {
+						client->GetPlayer()->AddItem(new Item(itr->second));
+						client->GetPlayer()->ClearPendingSelectableItemRewards(itr->first);
+					}
+				}
+			}
+			if (collectedItems) {
+				EQ2Packet* outapp = client->GetPlayer()->SendInventoryUpdate(client->GetVersion());
+				if (outapp)
+					client->QueuePacket(outapp);
+			}
 			else
 			else
 				LogWrite(COMMAND__ERROR, 0, "Command", "Error in COMMAND_ACCEPT_REWARD. No pending quest or collection reward was found (unknown=%u).", unknown);
 				LogWrite(COMMAND__ERROR, 0, "Command", "Error in COMMAND_ACCEPT_REWARD. No pending quest or collection reward was found (unknown=%u).", unknown);
 			break;
 			break;
@@ -4758,7 +4784,7 @@ void Commands::Command_Follow(Client* client, Seperator* sep)
 		client->GetPlayer()->changed = true;
 		client->GetPlayer()->changed = true;
 	}
 	}
 	else
 	else
-		client->Message(CHANNEL_COLOR_WHITE, "You must first select a group member to follow.");
+		client->Message(CHANNEL_NARRATIVE, "You must first select a group member to follow.");
 }
 }
 
 
 /* 
 /* 
@@ -4904,7 +4930,7 @@ void Commands::Command_Guild(Client* client, Seperator* sep)
 					if (target->IsPlayer())
 					if (target->IsPlayer())
 						guild->InvitePlayer(client, target->GetName());
 						guild->InvitePlayer(client, target->GetName());
 					else
 					else
-						client->Message(CHANNEL_COLOR_WHITE, "%s is not a player.", target->GetName());
+						client->Message(CHANNEL_NARRATIVE, "%s is not a player.", target->GetName());
 				}
 				}
 			}
 			}
 		}
 		}
@@ -4925,7 +4951,7 @@ void Commands::Command_Guild(Client* client, Seperator* sep)
 				Client* client_inviter = pgi->invited_by->GetZone()->GetClientBySpawn(pgi->invited_by);
 				Client* client_inviter = pgi->invited_by->GetZone()->GetClientBySpawn(pgi->invited_by);
 
 
 				if (client_inviter)
 				if (client_inviter)
-					client_inviter->Message(CHANNEL_COLOR_WHITE, "%s has declined your invitation to join %s.", client->GetPlayer()->GetName(), pgi->guild->GetName());
+					client_inviter->Message(CHANNEL_NARRATIVE, "%s has declined your invitation to join %s.", client->GetPlayer()->GetName(), pgi->guild->GetName());
 			}
 			}
 			client->SetPendingGuildInvite(0);
 			client->SetPendingGuildInvite(0);
 		}
 		}
@@ -4936,7 +4962,7 @@ void Commands::Command_Guild(Client* client, Seperator* sep)
 			if (!guild_list.GetGuild(guild_name))
 			if (!guild_list.GetGuild(guild_name))
 				world.CreateGuild(guild_name, client, client->GetPlayer()->GetGroupMemberInfo() ? client->GetPlayer()->GetGroupMemberInfo()->group_id : 0);
 				world.CreateGuild(guild_name, client, client->GetPlayer()->GetGroupMemberInfo() ? client->GetPlayer()->GetGroupMemberInfo()->group_id : 0);
 			else
 			else
-				client->SimpleMessage(CHANNEL_COLOR_WHITE, "A guild with that name already exists.");
+				client->SimpleMessage(CHANNEL_NARRATIVE, "A guild with that name already exists.");
 		}
 		}
 		else if (strncmp(command, "search", length) == 0)
 		else if (strncmp(command, "search", length) == 0)
 			client->ShowGuildSearchWindow();
 			client->ShowGuildSearchWindow();
@@ -5034,7 +5060,7 @@ void Commands::Command_GuildSay(Client* client, Seperator* sep)
 			guild->HandleGuildSay(client, sep->argplus[0]);
 			guild->HandleGuildSay(client, sep->argplus[0]);
 	}
 	}
 	else
 	else
-		client->SimpleMessage(CHANNEL_COLOR_WHITE, "You are not a member of a guild");
+		client->SimpleMessage(CHANNEL_NARRATIVE, "You are not a member of a guild");
 }
 }
 
 
 /* 
 /* 
@@ -5052,7 +5078,7 @@ void Commands::Command_OfficerSay(Client* client, Seperator* sep)
 			guild->HandleOfficerSay(client, sep->argplus[0]);
 			guild->HandleOfficerSay(client, sep->argplus[0]);
 	}
 	}
 	else
 	else
-		client->SimpleMessage(CHANNEL_COLOR_WHITE, "You are not a member of a guild");
+		client->SimpleMessage(CHANNEL_NARRATIVE, "You are not a member of a guild");
 }
 }
 
 
 /* 
 /* 
@@ -5697,12 +5723,12 @@ void Commands::Command_Languages(Client* client, Seperator* sep)
 	list<Language*>* languages = client->GetPlayer()->GetPlayerLanguages()->GetAllLanguages();
 	list<Language*>* languages = client->GetPlayer()->GetPlayerLanguages()->GetAllLanguages();
 	list<Language*>::iterator itr;
 	list<Language*>::iterator itr;
 	Language* language;
 	Language* language;
-	client->Message(CHANNEL_COLOR_WHITE, "You know the following languages:");
+	client->Message(CHANNEL_NARRATIVE, "You know the following languages:");
 
 
 	for(itr = languages->begin(); itr != languages->end(); itr++)
 	for(itr = languages->begin(); itr != languages->end(); itr++)
 	{
 	{
 		language = *itr;
 		language = *itr;
-		client->Message(CHANNEL_COLOR_WHITE, "%s", language->GetName());
+		client->Message(CHANNEL_NARRATIVE, "%s", language->GetName());
 	}
 	}
 }
 }
 
 
@@ -5728,7 +5754,7 @@ void Commands::Command_SetLanguage(Client* client, Seperator* sep)
 			{
 			{
 				database.SaveCharacterCurrentLang(0, client->GetCharacterID(), client);
 				database.SaveCharacterCurrentLang(0, client->GetCharacterID(), client);
 				client->SendLanguagesUpdate(0);
 				client->SendLanguagesUpdate(0);
-				client->Message(CHANNEL_COLOR_WHITE, "You are now speaking %s", value);
+				client->Message(CHANNEL_NARRATIVE, "You are now speaking %s", value);
 			}
 			}
 			else
 			else
 			{
 			{
@@ -5737,10 +5763,10 @@ void Commands::Command_SetLanguage(Client* client, Seperator* sep)
 					Language* language = player->GetPlayerLanguages()->GetLanguageByName(value);
 					Language* language = player->GetPlayerLanguages()->GetLanguageByName(value);
 					database.SaveCharacterCurrentLang(language->GetID(), client->GetCharacterID(), client);
 					database.SaveCharacterCurrentLang(language->GetID(), client->GetCharacterID(), client);
 					client->SendLanguagesUpdate(language->GetID());
 					client->SendLanguagesUpdate(language->GetID());
-					client->Message(CHANNEL_COLOR_WHITE, "You are now speaking %s", language->GetName());
+					client->Message(CHANNEL_NARRATIVE, "You are now speaking %s", language->GetName());
 				}
 				}
 				else
 				else
-					client->Message(CHANNEL_COLOR_WHITE, "You do not know how to speak %s", value);
+					client->Message(CHANNEL_NARRATIVE, "You do not know how to speak %s", value);
 			}
 			}
 		}
 		}
 		else
 		else
@@ -5753,12 +5779,12 @@ void Commands::Command_SetLanguage(Client* client, Seperator* sep)
 				Language* language = player->GetPlayerLanguages()->GetLanguage(id);
 				Language* language = player->GetPlayerLanguages()->GetLanguage(id);
 				database.SaveCharacterCurrentLang(id, client->GetCharacterID(), client);
 				database.SaveCharacterCurrentLang(id, client->GetCharacterID(), client);
 				client->SendLanguagesUpdate(id);
 				client->SendLanguagesUpdate(id);
-				client->Message(CHANNEL_COLOR_WHITE, "You are now speaking %s", language->GetName());
+				client->Message(CHANNEL_NARRATIVE, "You are now speaking %s", language->GetName());
 			}
 			}
 			else
 			else
 			{
 			{
 				Language* language = master_languages_list.GetLanguage(id);
 				Language* language = master_languages_list.GetLanguage(id);
-				client->Message(CHANNEL_COLOR_WHITE, "You do not know how to speak %s", language->GetName());
+				client->Message(CHANNEL_NARRATIVE, "You do not know how to speak %s", language->GetName());
 			}
 			}
 		}
 		}
 	}
 	}
@@ -5770,10 +5796,10 @@ void Commands::Command_SetLanguage(Client* client, Seperator* sep)
 		if(id > 0)
 		if(id > 0)
 		{
 		{
 			Language* language = player->GetPlayerLanguages()->GetLanguage(id);
 			Language* language = player->GetPlayerLanguages()->GetLanguage(id);
-			client->Message(CHANNEL_COLOR_WHITE, "You are currently speaking %s ", language->GetName());
+			client->Message(CHANNEL_NARRATIVE, "You are currently speaking %s ", language->GetName());
 		}
 		}
 		else
 		else
-			client->Message(CHANNEL_COLOR_WHITE, "You are currently speaking Common");
+			client->Message(CHANNEL_NARRATIVE, "You are currently speaking Common");
 	}
 	}
 }
 }
 
 
@@ -7576,11 +7602,11 @@ void Commands::Command_TitleList(Client* client)
 	Title* title;
 	Title* title;
 	int16 i = 0;
 	int16 i = 0;
 
 
-	client->Message(CHANNEL_COLOR_WHITE, "Listing available titles:");
+	client->Message(CHANNEL_NARRATIVE, "Listing available titles:");
 	for(itr = titles->begin(); itr != titles->end(); itr++)
 	for(itr = titles->begin(); itr != titles->end(); itr++)
 	{
 	{
 		title = *itr;
 		title = *itr;
-		client->Message(CHANNEL_COLOR_WHITE, "%i: type=[%s] title=[%s]", i, title->GetPrefix() ? "Prefix":"Suffix", title->GetName());
+		client->Message(CHANNEL_NARRATIVE, "%i: type=[%s] title=[%s]", i, title->GetPrefix() ? "Prefix":"Suffix", title->GetName());
 		i++;
 		i++;
 	}
 	}
 
 
@@ -7679,9 +7705,9 @@ void Commands::Command_Toggle_AutoConsume(Client* client, Seperator* sep)
 			player->SetCharSheetChanged(true);
 			player->SetCharSheetChanged(true);
 			client->QueuePacket(player->GetEquipmentList()->serialize(client->GetVersion(), player));
 			client->QueuePacket(player->GetEquipmentList()->serialize(client->GetVersion(), player));
 			if (flag == 1)
 			if (flag == 1)
-				client->Message(CHANNEL_COLOR_WHITE, "You decide to eat immediately whenever you become hungry.");
+				client->Message(CHANNEL_NARRATIVE, "You decide to eat immediately whenever you become hungry.");
 			else
 			else
-				client->Message(CHANNEL_COLOR_WHITE, "You decide to ignore the hunger.");
+				client->Message(CHANNEL_NARRATIVE, "You decide to ignore the hunger.");
 		}
 		}
 		else
 		else
 		{
 		{
@@ -7689,9 +7715,9 @@ void Commands::Command_Toggle_AutoConsume(Client* client, Seperator* sep)
 			player->SetCharSheetChanged(true);
 			player->SetCharSheetChanged(true);
 			client->QueuePacket(player->GetEquipmentList()->serialize(client->GetVersion(), player));
 			client->QueuePacket(player->GetEquipmentList()->serialize(client->GetVersion(), player));
 			if (flag == 1)
 			if (flag == 1)
-				client->Message(CHANNEL_COLOR_WHITE, "You decide to drink immediately whenever you become thirsty.");
+				client->Message(CHANNEL_NARRATIVE, "You decide to drink immediately whenever you become thirsty.");
 			else
 			else
-				client->Message(CHANNEL_COLOR_WHITE, "You decide to ignore the thirst.");
+				client->Message(CHANNEL_NARRATIVE, "You decide to ignore the thirst.");
 		}
 		}
 	}
 	}
 }
 }
@@ -8275,17 +8301,17 @@ void Commands::Command_JoinChannel(Client * client, Seperator *sep) {
 	}
 	}
 
 
 	if (chat.IsInChannel(client, channel_name)) {
 	if (chat.IsInChannel(client, channel_name)) {
-		client->Message(CHANNEL_COLOR_WHITE, "You are already in '%s'.", channel_name);
+		client->Message(CHANNEL_NARRATIVE, "You are already in '%s'.", channel_name);
 		return;
 		return;
 	}
 	}
 
 
 	if (chat.HasPassword(channel_name)) {
 	if (chat.HasPassword(channel_name)) {
 		if (password == NULL) {
 		if (password == NULL) {
-			client->Message(CHANNEL_COLOR_WHITE, "Unable to join '%s': That channel is password protected.", channel_name);
+			client->Message(CHANNEL_NARRATIVE, "Unable to join '%s': That channel is password protected.", channel_name);
 			return;
 			return;
 		}
 		}
 		if (!chat.PasswordMatches(channel_name, password)) {
 		if (!chat.PasswordMatches(channel_name, password)) {
-			client->Message(CHANNEL_COLOR_WHITE, "Unable to join '%s': The password is not correc.t", channel_name);
+			client->Message(CHANNEL_NARRATIVE, "Unable to join '%s': The password is not correc.t", channel_name);
 			return;
 			return;
 		}
 		}
 	}
 	}
@@ -8377,9 +8403,8 @@ void Commands::Command_Test(Client* client, EQ2_16BitString* command_parms) {
 			}
 			}
 		}
 		}
 		else if (atoi(sep->arg[0]) == 5) {
 		else if (atoi(sep->arg[0]) == 5) {
-			client->GetPlayer()->GetTarget();
-			int16 offset = atoi(sep->arg[2]);
-			int32 value1 = atol(sep->arg[4]);
+			int16 offset = atoi(sep->arg[0]);
+			int32 value1 = atol(sep->arg[1]);
 			EQ2Packet* outapp = client->GetPlayer()->GetPlayerInfo()->serialize(client->GetVersion(), offset, value1);
 			EQ2Packet* outapp = client->GetPlayer()->GetPlayerInfo()->serialize(client->GetVersion(), offset, value1);
 			client->QueuePacket(outapp);
 			client->QueuePacket(outapp);
 		}
 		}
@@ -8465,67 +8490,39 @@ void Commands::Command_Test(Client* client, EQ2_16BitString* command_parms) {
 					value2 = atol(sep->arg[7]);
 					value2 = atol(sep->arg[7]);
 				}
 				}
 				sprintf(spawn->appearance.name, "Offset %i to %i", offset, offset2);
 				sprintf(spawn->appearance.name, "Offset %i to %i", offset, offset2);
+				spawn->AddPrimaryEntityCommand("attack", 10000, "attack","", 0, 0);
 				EQ2Packet* ret = spawn->spawn_serialize(client->GetPlayer(), client->GetVersion(), offset, value1, offset2, offset3, offset4, value2);
 				EQ2Packet* ret = spawn->spawn_serialize(client->GetPlayer(), client->GetVersion(), offset, value1, offset2, offset3, offset4, value2);
 				DumpPacket(ret);
 				DumpPacket(ret);
 				client->QueuePacket(ret);
 				client->QueuePacket(ret);
 			}
 			}
 		}
 		}
 		else if (atoi(sep->arg[0]) == 9) {
 		else if (atoi(sep->arg[0]) == 9) {
-			Item* item = master_item_list.GetItem(70007);
-			EQ2Packet* app = item->serialize(client->GetVersion(), true, client->GetPlayer());
-			if (sep->IsSet(2)) {
-				int8 offset = atoi(sep->arg[1]);
-				uchar* ptr2 = app->pBuffer;
-				ptr2 += offset;
-				if (sep->IsNumber(2)) {
-					int32 value1 = atol(sep->arg[2]);
-					if (value1 > 0xFFFF)
-						memcpy(ptr2, (uchar*)&value1, 4);
-					else if (value1 > 0xFF)
-						memcpy(ptr2, (uchar*)&value1, 2);
-					else
-						memcpy(ptr2, (uchar*)&value1, 1);
-				}
-				else {
-					int8 len = strlen(sep->arg[2]);
-					memcpy(ptr2, (uchar*)&len, 1);
-					ptr2 += 1;
-					memcpy(ptr2, sep->arg[2], len);
+			Spawn* spawn = client->GetPlayer()->GetTarget();
+			if (spawn) {	
+				if (sep->IsSet(3)) {
+					int32 amount = (int32)atoi(sep->arg[3]);
+					spawn->SetActivityStatus(amount);
 				}
 				}
-			}
-			if (sep->IsSet(4)) {
-				int8 offset = atoi(sep->arg[3]);
-				uchar* ptr2 = app->pBuffer;
-				ptr2 += offset;
-				if (sep->IsNumber(4)) {
-					int32 value1 = atol(sep->arg[4]);
-					if (value1 > 0xFFFF)
-						memcpy(ptr2, (uchar*)&value1, 4);
-					else if (value1 > 0xFF)
-						memcpy(ptr2, (uchar*)&value1, 2);
-					else
-						memcpy(ptr2, (uchar*)&value1, 1);
+				if (sep->IsSet(2)) {
+					int8 amount = (int8)atoi(sep->arg[2]);
+					spawn->SetLockedNoLoot(amount);
 				}
 				}
-				else {
-					int8 len = strlen(sep->arg[4]);
-					memcpy(ptr2, (uchar*)&len, 1);
-					ptr2 += 1;
-					memcpy(ptr2, sep->arg[4], len);
+				if (sep->IsSet(1)) {
+					sint8 amount = (sint8)atoi(sep->arg[1]);
+					spawn->AddIconValue(amount);
 				}
 				}
 			}
 			}
-			DumpPacket(app);
-			client->QueuePacket(app);
 		}
 		}
 		else if (atoi(sep->arg[0]) == 10) {
 		else if (atoi(sep->arg[0]) == 10) {
 			PacketStruct* packet2 = configReader.getStruct("WS_QuestJournalUpdate", client->GetVersion());
 			PacketStruct* packet2 = configReader.getStruct("WS_QuestJournalUpdate", client->GetVersion());
 			if (packet2) {
 			if (packet2) {
 				packet2->setArrayLengthByName("num_quests", 1);
 				packet2->setArrayLengthByName("num_quests", 1);
 				packet2->setArrayDataByName("active", 1);
 				packet2->setArrayDataByName("active", 1);
-				packet2->setArrayDataByName("name", "Archetype Selection");
+				packet2->setArrayDataByName("name", "Tasks aboard the Far Journey");
 				packet2->setArrayDataByName("quest_type", "Hallmark");
 				packet2->setArrayDataByName("quest_type", "Hallmark");
 				packet2->setArrayDataByName("quest_zone", "Hallmark");
 				packet2->setArrayDataByName("quest_zone", "Hallmark");
 				packet2->setArrayDataByName("journal_updated", 1);
 				packet2->setArrayDataByName("journal_updated", 1);
-				packet2->setArrayDataByName("quest_id", 5);
+				packet2->setArrayDataByName("quest_id", 524);
 				packet2->setArrayDataByName("day", 19);
 				packet2->setArrayDataByName("day", 19);
 				packet2->setArrayDataByName("month", 6);
 				packet2->setArrayDataByName("month", 6);
 				packet2->setArrayDataByName("year", 20);
 				packet2->setArrayDataByName("year", 20);
@@ -8533,7 +8530,7 @@ void Commands::Command_Test(Client* client, EQ2_16BitString* command_parms) {
 				packet2->setArrayDataByName("encounter_level", 4);
 				packet2->setArrayDataByName("encounter_level", 4);
 				packet2->setArrayDataByName("difficulty", 3);
 				packet2->setArrayDataByName("difficulty", 3);
 				packet2->setArrayDataByName("visible", 1);
 				packet2->setArrayDataByName("visible", 1);
-				packet2->setDataByName("visible_quest_id", 5);
+				packet2->setDataByName("visible_quest_id", 524);
 				packet2->setDataByName("player_crc", 2900677088);
 				packet2->setDataByName("player_crc", 2900677088);
 				packet2->setDataByName("player_name", "LethalEncounter");
 				packet2->setDataByName("player_name", "LethalEncounter");
 				EQ2Packet* app = packet2->serialize();
 				EQ2Packet* app = packet2->serialize();
@@ -9409,7 +9406,7 @@ void Commands::Command_LeaveChannel(Client *client, Seperator *sep) {
 	channel_name = sep->arg[0];
 	channel_name = sep->arg[0];
 
 
 	if (!chat.IsInChannel(client, channel_name))
 	if (!chat.IsInChannel(client, channel_name))
-		client->Message(CHANNEL_COLOR_WHITE, "Unable to leave '%s': You are not in the channel.", channel_name);
+		client->Message(CHANNEL_NARRATIVE, "Unable to leave '%s': You are not in the channel.", channel_name);
 	else if (!chat.LeaveChannel(client, channel_name))
 	else if (!chat.LeaveChannel(client, channel_name))
 		client->SimpleMessage(CHANNEL_COLOR_YELLOW, "There was an internal error preventing you from leaving that channel MUAHAHA");
 		client->SimpleMessage(CHANNEL_COLOR_YELLOW, "There was an internal error preventing you from leaving that channel MUAHAHA");
 }
 }
@@ -9747,9 +9744,9 @@ void Commands::Command_ConsumeFood(Client* client, Seperator* sep) {
 			if(item->GetItemScript() && lua_interface){
 			if(item->GetItemScript() && lua_interface){
 				lua_interface->RunItemScript(item->GetItemScript(), "cast", item, client->GetPlayer());
 				lua_interface->RunItemScript(item->GetItemScript(), "cast", item, client->GetPlayer());
 				if (slot == 22)
 				if (slot == 22)
-					client->Message(CHANNEL_COLOR_WHITE, "You eat a %s.", item->name.c_str());
+					client->Message(CHANNEL_NARRATIVE, "You eat a %s.", item->name.c_str());
 				else
 				else
-					client->Message(CHANNEL_COLOR_WHITE, "You drink a %s.", item->name.c_str());
+					client->Message(CHANNEL_NARRATIVE, "You drink a %s.", item->name.c_str());
 			}
 			}
 		}
 		}
 
 

+ 3 - 43
EQ2/source/WorldServer/Commands/Commands.h

@@ -37,52 +37,12 @@ extern map<int16,OpcodeManager*>EQOpcodeManager;
 #define CHANNEL_COLOR_RED				3
 #define CHANNEL_COLOR_RED				3
 #define CHANNEL_COLOR_CHAT_RELATIONSHIP	4
 #define CHANNEL_COLOR_CHAT_RELATIONSHIP	4
 #define CHANNEL_COLOR_YELLOW			5
 #define CHANNEL_COLOR_YELLOW			5
-#define CHANNEL_COLOR_REVIVE			12
-#define CHANNEL_COLOR_MAIL				12
-#define CHANNEL_COLOR_WHITE				12
-#define CHANNEL_COLOR_GROUP				15
-#define CHANNEL_COLOR_GUILD				18
-#define CHANNEL_COLOR_GUILD_MOTD		20
-#define CHANNEL_COLOR_GUILD_EVENT		22
-#define CHANNEL_COLOR_EXP				36
-#define CHANNEL_COLOR_SKILL				39
-#define CHANNEL_COLOR_FACTION			40
-#define CHANNEL_COLOR_SPELL_EFFECT		42
-#define CHANNEL_COLOR_SPELL				47
-#define CHANNEL_COLOR_SPELL_INTERRUPT	52
-#define CHANNEL_COLOR_SPELL_FADE		51
-#define CHANNEL_COLOR_COMBAT			60
-#define CHANNEL_COLOR_LOOT				81
 #define CHANNEL_COLOR_NEW_LOOT			84
 #define CHANNEL_COLOR_NEW_LOOT			84
 #define CHANNEL_COLOR_NEWEST_LOOT		89
 #define CHANNEL_COLOR_NEWEST_LOOT		89
-#define CHANNEL_COLOR_MERCHANT			88
-#define CHANNEL_COLOR_GROUP_INVITE		89
-#define CHANNEL_COLOR_GUILD_MSGS		94
-#define CHANNEL_COLOR_HARVEST			96
 
 
 #define UPDATE_COLOR_WHITE				254  // For UpdateText
 #define UPDATE_COLOR_WHITE				254  // For UpdateText
 
 
-#define CHANNEL_SAY			8
-#define CHANNEL_SHOUT		9
-#define CHANNEL_EMOTE		10
-#define CHANNEL_GROUP		15
-#define CHANNEL_RAID		16
-#define CHANNEL_GUILD		18
-#define CHANNEL_OFFICER		19
-#define CHANNEL_SAYTARGET	25 // you say to xxx
-#define CHANNEL_TELL		28 // you tell xxx
-#define CHANNEL_OOC			32
-//#define CHANNEL_AUCTION		30
-
-#define CLASSIC_CLIENT_CHANNEL_GROUP		14
-#define CLASSIC_CLIENT_CHANNEL_RAID			15
-#define CLASSIC_CLIENT_CHANNEL_GUILD		17
-#define CLASSIC_CLIENT_CHANNEL_SAYTARGET	21 // you say to xxx
-#define CLASSIC_CLIENT_CHANNEL_TELL			22 // you tell xxx
-#define CLASSIC_CLIENT_CHANNEL_OOC			25
-#define CLASSIC_CLIENT_CHANNEL_AUCTION		26
-#define CLASSIC_CLIENT_CHANNEL_BROADCAST	61
-
+#define CHANNEL_ALL_TEXT					0
 #define CHANNEL_GAME_TEXT					1
 #define CHANNEL_GAME_TEXT					1
 #define CHANNEL_DEFAULT						2
 #define CHANNEL_DEFAULT						2
 #define CHANNEL_ERROR						3
 #define CHANNEL_ERROR						3
@@ -94,7 +54,7 @@ extern map<int16,OpcodeManager*>EQOpcodeManager;
 #define CHANNEL_SHOUT						9
 #define CHANNEL_SHOUT						9
 #define CHANNEL_EMOTE						10
 #define CHANNEL_EMOTE						10
 #define CHANNEL_YELL						11
 #define CHANNEL_YELL						11
-#define CHANNEL_NARRATIVE					12
+#define CHANNEL_NARRATIVE					12 //white
 #define CHANNEL_NONPLAYER_SAY				13
 #define CHANNEL_NONPLAYER_SAY				13
 #define CHANNEL_GROUP_CHAT					14
 #define CHANNEL_GROUP_CHAT					14
 #define CHANNEL_GROUP_SAY					15 // Use this for group chat
 #define CHANNEL_GROUP_SAY					15 // Use this for group chat
@@ -116,7 +76,7 @@ extern map<int16,OpcodeManager*>EQOpcodeManager;
 #define CHANNEL_CHAT_CHANNEL_TEXT			31
 #define CHANNEL_CHAT_CHANNEL_TEXT			31
 #define CHANNEL_OUT_OF_CHARACTER			32
 #define CHANNEL_OUT_OF_CHARACTER			32
 #define CHANNEL_AUCTION						33
 #define CHANNEL_AUCTION						33
-// 34 is nothing, message with 34 as type will not show on client
+#define CHANNEL_CUSTOM_CHANNEL				34 // 34 is nothing, message with 34 as type will not show on client
 #define CHANNEL_CHARACTER_TEXT				35
 #define CHANNEL_CHARACTER_TEXT				35
 #define CHANNEL_REWARD						36
 #define CHANNEL_REWARD						36
 #define CHANNEL_DEATH						37
 #define CHANNEL_DEATH						37

+ 6 - 6
EQ2/source/WorldServer/GroundSpawn.cpp

@@ -381,7 +381,7 @@ void GroundSpawn::ProcessHarvest(Client* client) {
 						item->details.count = reward_total;
 						item->details.count = reward_total;
 
 
 						// chat box update for normal item (todo: verify output text)
 						// chat box update for normal item (todo: verify output text)
-						client->Message(CHANNEL_COLOR_HARVEST, "You %s %i \\aITEM %u %u:%s\\/a from the %s.", GetHarvestMessageName(true).c_str(), item->details.count, item->details.item_id, item->details.unique_id, item->name.c_str(), GetName());
+						client->Message(CHANNEL_HARVESTING, "You %s %i %s from the %s.", GetHarvestMessageName(true).c_str(), item->details.count, item->CreateItemLink(GetVersion(), true).c_str(), GetName());
 						// add Normal item to player inventory
 						// add Normal item to player inventory
 						client->AddItem(item);
 						client->AddItem(item);
 						//Check if the player has a harvesting quest for this
 						//Check if the player has a harvesting quest for this
@@ -410,12 +410,12 @@ void GroundSpawn::ProcessHarvest(Client* client) {
 
 
 								// send Rare harvest message to client
 								// send Rare harvest message to client
 								sprintf(tmp, "\\#FFFF6ERare item found!\12%s: \\#C8FFFF%i %s", GetHarvestMessageName().c_str(), item_rare->details.count, item_rare->name.c_str());
 								sprintf(tmp, "\\#FFFF6ERare item found!\12%s: \\#C8FFFF%i %s", GetHarvestMessageName().c_str(), item_rare->details.count, item_rare->name.c_str());
-								client->Message(CHANNEL_COLOR_HARVEST, "You have found a rare item!");
+								client->Message(CHANNEL_HARVESTING, "You have found a rare item!");
 								client->SendPopupMessage(11, tmp, "ui_harvested_rare", 2.25, 0xFF, 0xFF, 0xFF);
 								client->SendPopupMessage(11, tmp, "ui_harvested_rare", 2.25, 0xFF, 0xFF, 0xFF);
 								client->GetPlayer()->UpdatePlayerStatistic(STAT_PLAYER_RARES_HARVESTED, item_rare->details.count);
 								client->GetPlayer()->UpdatePlayerStatistic(STAT_PLAYER_RARES_HARVESTED, item_rare->details.count);
 
 
 								// chat box update for rare item (todo: verify output text)
 								// chat box update for rare item (todo: verify output text)
-								client->Message(CHANNEL_COLOR_HARVEST, "You %s %i \\aITEM %u %u:%s\\/a from the %s.", GetHarvestMessageName(true).c_str(), item_rare->details.count, item_rare->details.item_id, item_rare->details.unique_id, item_rare->name.c_str(), GetName());
+								client->Message(CHANNEL_HARVESTING, "You %s %i %s from the %s.", GetHarvestMessageName(true).c_str(), item_rare->details.count, item->CreateItemLink(GetVersion(), true).c_str(), GetName());
 								// add Rare item to player inventory
 								// add Rare item to player inventory
 								client->AddItem(item_rare);
 								client->AddItem(item_rare);
 								//Check if the player has a harvesting quest for this
 								//Check if the player has a harvesting quest for this
@@ -428,7 +428,7 @@ void GroundSpawn::ProcessHarvest(Client* client) {
 
 
 							// send Rare harvest message to client
 							// send Rare harvest message to client
 							sprintf(tmp, "\\#FFFF6ERare item found!\12%s: \\#C8FFFF%i %s", GetHarvestMessageName().c_str(), item->details.count, item->name.c_str());
 							sprintf(tmp, "\\#FFFF6ERare item found!\12%s: \\#C8FFFF%i %s", GetHarvestMessageName().c_str(), item->details.count, item->name.c_str());
-							client->Message(CHANNEL_COLOR_HARVEST, "You have found a rare item!");
+							client->Message(CHANNEL_HARVESTING, "You have found a rare item!");
 							client->SendPopupMessage(11, tmp, "ui_harvested_rare", 2.25, 0xFF, 0xFF, 0xFF);
 							client->SendPopupMessage(11, tmp, "ui_harvested_rare", 2.25, 0xFF, 0xFF, 0xFF);
 							client->GetPlayer()->UpdatePlayerStatistic(STAT_PLAYER_RARES_HARVESTED, item->details.count);
 							client->GetPlayer()->UpdatePlayerStatistic(STAT_PLAYER_RARES_HARVESTED, item->details.count);
 						}
 						}
@@ -452,13 +452,13 @@ void GroundSpawn::ProcessHarvest(Client* client) {
 				else {
 				else {
 					// if no item harvested
 					// if no item harvested
 					LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "No item_harvested");
 					LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "No item_harvested");
-					client->Message(CHANNEL_COLOR_HARVEST, "You failed to %s anything from %s.", GetHarvestMessageName(true, true).c_str(), GetName());
+					client->Message(CHANNEL_HARVESTING, "You failed to %s anything from %s.", GetHarvestMessageName(true, true).c_str(), GetName());
 				}
 				}
 			}
 			}
 			else {
 			else {
 				// if no harvest type
 				// if no harvest type
 				LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "No harvest_type");
 				LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "No harvest_type");
-				client->Message(CHANNEL_COLOR_HARVEST, "You failed to %s anything from %s.", GetHarvestMessageName(true, true).c_str(), GetName());
+				client->Message(CHANNEL_HARVESTING, "You failed to %s anything from %s.", GetHarvestMessageName(true, true).c_str(), GetName());
 			}
 			}
 		}
 		}
 	} // cycle through num_attempts_per_harvest
 	} // cycle through num_attempts_per_harvest

+ 27 - 27
EQ2/source/WorldServer/Guilds/Guild.cpp

@@ -689,9 +689,9 @@ bool Guild::AddNewGuildMember(Client *client, const char *invited_by, int8 rank)
 		player->SetSubTitle(subtitle.c_str());
 		player->SetSubTitle(subtitle.c_str());
 
 
 		if (invited_by)
 		if (invited_by)
-			client->SimpleMessage(CHANNEL_COLOR_WHITE, "You accept the invite into the guild.");
+			client->SimpleMessage(CHANNEL_NARRATIVE, "You accept the invite into the guild.");
 		else {
 		else {
-			client->SimpleMessage(CHANNEL_COLOR_WHITE, "You have formed the guild.");
+			client->SimpleMessage(CHANNEL_NARRATIVE, "You have formed the guild.");
 			LogWrite(GUILD__DEBUG, 0, "Guilds", "New Guild formed: %s", GetName());
 			LogWrite(GUILD__DEBUG, 0, "Guilds", "New Guild formed: %s", GetName());
 		}
 		}
 
 
@@ -911,7 +911,7 @@ bool Guild::InvitePlayer(Client *client, const char *name, bool send_packet) {
 	assert(name);
 	assert(name);
 
 
 	if (!(client_invite = zone_list.GetClientByCharName(string(name)))) {
 	if (!(client_invite = zone_list.GetClientByCharName(string(name)))) {
-		client->Message(CHANNEL_COLOR_WHITE, "%s couldn't be found.", name);
+		client->Message(CHANNEL_NARRATIVE, "%s couldn't be found.", name);
 		LogWrite(GUILD__WARNING, 0, "Guilds", "Attempted to invite %s to guild %s: Player Not Found", name, GetName());
 		LogWrite(GUILD__WARNING, 0, "Guilds", "Attempted to invite %s to guild %s: Player Not Found", name, GetName());
 		return false;
 		return false;
 	}
 	}
@@ -919,13 +919,13 @@ bool Guild::InvitePlayer(Client *client, const char *name, bool send_packet) {
 	player_invite = client_invite->GetPlayer();
 	player_invite = client_invite->GetPlayer();
 
 
 	if (player_invite->GetGuild()) {
 	if (player_invite->GetGuild()) {
-		client->Message(CHANNEL_COLOR_WHITE, "%s is already in a guild.", player_invite->GetName());
+		client->Message(CHANNEL_NARRATIVE, "%s is already in a guild.", player_invite->GetName());
 		LogWrite(GUILD__WARNING, 0, "Guilds", "Attempted to invite %s to guild %s: Already in a guild", player_invite->GetName(), GetName());
 		LogWrite(GUILD__WARNING, 0, "Guilds", "Attempted to invite %s to guild %s: Already in a guild", player_invite->GetName(), GetName());
 		return false;
 		return false;
 	}
 	}
 
 
 	if (client_invite->GetPendingGuildInvite()->guild) {
 	if (client_invite->GetPendingGuildInvite()->guild) {
-		client->Message(CHANNEL_COLOR_WHITE, "%s is already considering joining a guild.", player_invite->GetName());
+		client->Message(CHANNEL_NARRATIVE, "%s is already considering joining a guild.", player_invite->GetName());
 		LogWrite(GUILD__WARNING, 0, "Guilds", "Attempted to invite %s to guild %s: Pending Invite elsewhere", player_invite->GetName(), GetName());
 		LogWrite(GUILD__WARNING, 0, "Guilds", "Attempted to invite %s to guild %s: Pending Invite elsewhere", player_invite->GetName(), GetName());
 		return false;
 		return false;
 	}
 	}
@@ -939,7 +939,7 @@ bool Guild::InvitePlayer(Client *client, const char *name, bool send_packet) {
 	packet->setMediumStringByName("guild_name", GetName());
 	packet->setMediumStringByName("guild_name", GetName());
 	client_invite->QueuePacket(packet->serialize());
 	client_invite->QueuePacket(packet->serialize());
 
 
-	client->Message(CHANNEL_COLOR_WHITE, "You have invited %s to join %s.", player_invite->GetName(), GetName());
+	client->Message(CHANNEL_NARRATIVE, "You have invited %s to join %s.", player_invite->GetName(), GetName());
 	LogWrite(GUILD__DEBUG, 0, "Guilds", "%s invited %s to guild %s", client->GetPlayer()->GetName(), player_invite->GetName(), GetName());
 	LogWrite(GUILD__DEBUG, 0, "Guilds", "%s invited %s to guild %s", client->GetPlayer()->GetName(), player_invite->GetName(), GetName());
 
 
 	client_invite->SetPendingGuildInvite(this, client->GetPlayer());
 	client_invite->SetPendingGuildInvite(this, client->GetPlayer());
@@ -972,7 +972,7 @@ bool Guild::AddPointsToAll(Client *client, float points, const char *comment, bo
 		AddPointHistory(gm, Timer::GetUnixTimeStamp(), client->GetPlayer()->GetName(), points, comment);
 		AddPointHistory(gm, Timer::GetUnixTimeStamp(), client->GetPlayer()->GetName(), points, comment);
 		if ((client_to = zone_list.GetClientByCharID(gm->character_id)))
 		if ((client_to = zone_list.GetClientByCharID(gm->character_id)))
 		{
 		{
-			client_to->Message(CHANNEL_COLOR_GUILD_MSGS, "%s increased your guild member points by %.1f.", client->GetPlayer()->GetName(), points);
+			client_to->Message(CHANNEL_GUILD_CHAT, "%s increased your guild member points by %.1f.", client->GetPlayer()->GetName(), points);
 			LogWrite(GUILD__DEBUG, 0, "Guilds", "Guild: %s", GetName());
 			LogWrite(GUILD__DEBUG, 0, "Guilds", "Guild: %s", GetName());
 			LogWrite(GUILD__DEBUG, 0, "Guilds", "\tAwarded By: %s +%.1f pts to Player: %s", client->GetPlayer()->GetName(), points, gm->name);
 			LogWrite(GUILD__DEBUG, 0, "Guilds", "\tAwarded By: %s +%.1f pts to Player: %s", client->GetPlayer()->GetName(), points, gm->name);
 		}
 		}
@@ -982,7 +982,7 @@ bool Guild::AddPointsToAll(Client *client, float points, const char *comment, bo
 	}
 	}
 	mMembers.releasereadlock(__FUNCTION__, __LINE__);
 	mMembers.releasereadlock(__FUNCTION__, __LINE__);
 
 
-	client->Message(CHANNEL_COLOR_GUILD_MSGS, "Points modified for %u guild members.", character_ids.size());
+	client->Message(CHANNEL_GUILD_CHAT, "Points modified for %u guild members.", character_ids.size());
 	if (send_packet) {
 	if (send_packet) {
 		LogWrite(GUILD__DEBUG, 0, "Guilds", "%s modified points for %u members. Reason: %s", client->GetPlayer()->GetName(), character_ids.size(), points, comment);
 		LogWrite(GUILD__DEBUG, 0, "Guilds", "%s modified points for %u members. Reason: %s", client->GetPlayer()->GetName(), character_ids.size(), points, comment);
 		SendGuildModification(points, &character_ids);
 		SendGuildModification(points, &character_ids);
@@ -1020,7 +1020,7 @@ bool Guild::AddPointsToAllOnline(Client *client, float points, const char *comme
 		character_ids.push_back(gm->character_id);
 		character_ids.push_back(gm->character_id);
 
 
 		AddPointHistory(gm, Timer::GetUnixTimeStamp(), client->GetPlayer()->GetName(), points, comment);
 		AddPointHistory(gm, Timer::GetUnixTimeStamp(), client->GetPlayer()->GetName(), points, comment);
-		client_to->Message(CHANNEL_COLOR_GUILD_MSGS, "%s increased your guild member points by %.1f.", client->GetPlayer()->GetName(), points);
+		client_to->Message(CHANNEL_GUILD_CHAT, "%s increased your guild member points by %.1f.", client->GetPlayer()->GetName(), points);
 		LogWrite(GUILD__DEBUG, 0, "Guilds", "Guild: %s", GetName());
 		LogWrite(GUILD__DEBUG, 0, "Guilds", "Guild: %s", GetName());
 		LogWrite(GUILD__DEBUG, 0, "Guilds", "\tAwarded By: %s +%.1f pts to Player: %s", client->GetPlayer()->GetName(), points, gm->name);
 		LogWrite(GUILD__DEBUG, 0, "Guilds", "\tAwarded By: %s +%.1f pts to Player: %s", client->GetPlayer()->GetName(), points, gm->name);
 
 
@@ -1030,7 +1030,7 @@ bool Guild::AddPointsToAllOnline(Client *client, float points, const char *comme
 	}
 	}
 	mMembers.releasereadlock(__FUNCTION__, __LINE__);
 	mMembers.releasereadlock(__FUNCTION__, __LINE__);
 
 
-	client->Message(CHANNEL_COLOR_GUILD_MSGS, "Points modified for %u guild members.", character_ids.size());
+	client->Message(CHANNEL_GUILD_CHAT, "Points modified for %u guild members.", character_ids.size());
 	if (send_packet) {
 	if (send_packet) {
 		LogWrite(GUILD__DEBUG, 0, "Guilds", "%s modified points for %u members. Reason: %s", client->GetPlayer()->GetName(), character_ids.size(), points, comment);
 		LogWrite(GUILD__DEBUG, 0, "Guilds", "%s modified points for %u members. Reason: %s", client->GetPlayer()->GetName(), character_ids.size(), points, comment);
 		SendGuildModification(points, &character_ids);
 		SendGuildModification(points, &character_ids);
@@ -1052,7 +1052,7 @@ bool Guild::AddPointsToGroup(Client *client, float points, const char *comment,
 	assert(client);
 	assert(client);
 
 
 	if (!client->GetPlayer()->GetGroupMemberInfo()) {
 	if (!client->GetPlayer()->GetGroupMemberInfo()) {
-		client->SimpleMessage(CHANNEL_COLOR_GUILD_MSGS, "Cannot assign points because you aren't in a group.");
+		client->SimpleMessage(CHANNEL_GUILD_CHAT, "Cannot assign points because you aren't in a group.");
 		LogWrite(GUILD__DEBUG, 0, "Guilds", "%s tried to assign points for group and failed: Not in a group", client->GetPlayer()->GetName());
 		LogWrite(GUILD__DEBUG, 0, "Guilds", "%s tried to assign points for group and failed: Not in a group", client->GetPlayer()->GetName());
 		return false;
 		return false;
 	}
 	}
@@ -1085,7 +1085,7 @@ bool Guild::AddPointsToGroup(Client *client, float points, const char *comment,
 			character_ids.push_back(gm->character_id);
 			character_ids.push_back(gm->character_id);
 
 
 			AddPointHistory(gm, Timer::GetUnixTimeStamp(), client->GetPlayer()->GetName(), points, comment);
 			AddPointHistory(gm, Timer::GetUnixTimeStamp(), client->GetPlayer()->GetName(), points, comment);
-			gmi->client->Message(CHANNEL_COLOR_GUILD_MSGS, "%s increased your guild member points by %.1f.", client->GetPlayer()->GetName(), points);
+			gmi->client->Message(CHANNEL_GUILD_CHAT, "%s increased your guild member points by %.1f.", client->GetPlayer()->GetName(), points);
 			LogWrite(GUILD__DEBUG, 0, "Guilds", "Guild: %s", GetName());
 			LogWrite(GUILD__DEBUG, 0, "Guilds", "Guild: %s", GetName());
 			LogWrite(GUILD__DEBUG, 0, "Guilds", "\tAwarded By: %s +%.1f pts to Player: %s", client->GetPlayer()->GetName(), points, gm->name);
 			LogWrite(GUILD__DEBUG, 0, "Guilds", "\tAwarded By: %s +%.1f pts to Player: %s", client->GetPlayer()->GetName(), points, gm->name);
 
 
@@ -1099,7 +1099,7 @@ bool Guild::AddPointsToGroup(Client *client, float points, const char *comment,
 	world.GetGroupManager()->ReleaseGroupLock(__FUNCTION__, __LINE__);
 	world.GetGroupManager()->ReleaseGroupLock(__FUNCTION__, __LINE__);
 	mMembers.releasereadlock(__FUNCTION__, __LINE__);
 	mMembers.releasereadlock(__FUNCTION__, __LINE__);
 
 
-	client->Message(CHANNEL_COLOR_GUILD_MSGS, "Points modified for %u guild members.", character_ids.size());
+	client->Message(CHANNEL_GUILD_CHAT, "Points modified for %u guild members.", character_ids.size());
 	if (send_packet) {
 	if (send_packet) {
 		LogWrite(GUILD__DEBUG, 0, "Guilds", "%s modified points for %u members. Reason: %s", client->GetPlayer()->GetName(), character_ids.size(), points, comment);
 		LogWrite(GUILD__DEBUG, 0, "Guilds", "%s modified points for %u members. Reason: %s", client->GetPlayer()->GetName(), character_ids.size(), points, comment);
 		SendGuildModification(points, &character_ids);
 		SendGuildModification(points, &character_ids);
@@ -1114,7 +1114,7 @@ bool Guild::AddPointsToRaid(Client *client, float points, const char *comment, b
 
 
 	assert(client);	
 	assert(client);	
 	LogWrite(MISC__TODO, 1, "TODO", "Implement Raiding\n%s, %s, %i", __FILE__, __FUNCTION__, __LINE__);
 	LogWrite(MISC__TODO, 1, "TODO", "Implement Raiding\n%s, %s, %i", __FILE__, __FUNCTION__, __LINE__);
-	client->SimpleMessage(CHANNEL_COLOR_GUILD_MSGS, "Cannot assign points because you aren't in a raid.");
+	client->SimpleMessage(CHANNEL_GUILD_CHAT, "Cannot assign points because you aren't in a raid.");
 	return false;
 	return false;
 }
 }
 
 
@@ -1134,7 +1134,7 @@ bool Guild::AddPointsToGuildMember(Client *client, float points, const char *nam
 	if (!permissions.Get(gm->rank)->Get(GUILD_PERMISSIONS_RECEIVE_POINTS)) {
 	if (!permissions.Get(gm->rank)->Get(GUILD_PERMISSIONS_RECEIVE_POINTS)) {
 		mMembers.releasereadlock(__FUNCTION__, __LINE__);
 		mMembers.releasereadlock(__FUNCTION__, __LINE__);
 		LogWrite(GUILD__DEBUG, 0, "Guilds", "PlayerID: %i not allowed to receive points! Skipping...", gm->character_id);
 		LogWrite(GUILD__DEBUG, 0, "Guilds", "PlayerID: %i not allowed to receive points! Skipping...", gm->character_id);
-		client->Message(CHANNEL_COLOR_GUILD_MSGS, "%s does not have permission to receive guild points.", gm->name);
+		client->Message(CHANNEL_GUILD_CHAT, "%s does not have permission to receive guild points.", gm->name);
 		return false;
 		return false;
 	}
 	}
 
 
@@ -1142,13 +1142,13 @@ bool Guild::AddPointsToGuildMember(Client *client, float points, const char *nam
 	character_ids.push_back(gm->character_id);
 	character_ids.push_back(gm->character_id);
 
 
 	if ((client_to = zone_list.GetClientByCharID(gm->character_id))) {
 	if ((client_to = zone_list.GetClientByCharID(gm->character_id))) {
-		client_to->Message(CHANNEL_COLOR_GUILD_MSGS, "%s increased your guild member points by %.1f.", client->GetPlayer()->GetName(), points);
+		client_to->Message(CHANNEL_GUILD_CHAT, "%s increased your guild member points by %.1f.", client->GetPlayer()->GetName(), points);
 		LogWrite(GUILD__DEBUG, 0, "Guilds", "Guild: %s", GetName());
 		LogWrite(GUILD__DEBUG, 0, "Guilds", "Guild: %s", GetName());
 		LogWrite(GUILD__DEBUG, 0, "Guilds", "\tAwarded By: %s +%.1f pts to Player: %s", client->GetPlayer()->GetName(), points, gm->name);
 		LogWrite(GUILD__DEBUG, 0, "Guilds", "\tAwarded By: %s +%.1f pts to Player: %s", client->GetPlayer()->GetName(), points, gm->name);
 	}
 	}
 
 
 	LogWrite(GUILD__DEBUG, 0, "Guilds", "%s modified points for 1 guild member. Reason: %s", client->GetPlayer()->GetName(), comment);
 	LogWrite(GUILD__DEBUG, 0, "Guilds", "%s modified points for 1 guild member. Reason: %s", client->GetPlayer()->GetName(), comment);
-	client->SimpleMessage(CHANNEL_COLOR_GUILD_MSGS, "Points modified for 1 guild member.");
+	client->SimpleMessage(CHANNEL_GUILD_CHAT, "Points modified for 1 guild member.");
 	AddPointHistory(gm, Timer::GetUnixTimeStamp(), client->GetPlayer()->GetName(), points, comment);
 	AddPointHistory(gm, Timer::GetUnixTimeStamp(), client->GetPlayer()->GetName(), points, comment);
 
 
 	if (send_packet) {
 	if (send_packet) {
@@ -1271,12 +1271,12 @@ bool Guild::ChangeMemberFlag(Client *client, int8 member_flag, int8 value, bool
 		case GUILD_MEMBER_FLAGS_NOTIFY_LOGINS: {
 		case GUILD_MEMBER_FLAGS_NOTIFY_LOGINS: {
 			if (value > 0 && !(gm->member_flags & GUILD_MEMBER_FLAGS_NOTIFY_LOGINS)) {
 			if (value > 0 && !(gm->member_flags & GUILD_MEMBER_FLAGS_NOTIFY_LOGINS)) {
 				gm->member_flags += GUILD_MEMBER_FLAGS_NOTIFY_LOGINS;
 				gm->member_flags += GUILD_MEMBER_FLAGS_NOTIFY_LOGINS;
-				client->SimpleMessage(CHANNEL_COLOR_GUILD_MSGS, "Guild online notifications are now enabled.");
+				client->SimpleMessage(CHANNEL_GUILD_CHAT, "Guild online notifications are now enabled.");
 				ret = true;
 				ret = true;
 			}
 			}
 			else if (value == 0 && gm->member_flags & GUILD_MEMBER_FLAGS_NOTIFY_LOGINS) {
 			else if (value == 0 && gm->member_flags & GUILD_MEMBER_FLAGS_NOTIFY_LOGINS) {
 				gm->member_flags -= GUILD_MEMBER_FLAGS_NOTIFY_LOGINS;
 				gm->member_flags -= GUILD_MEMBER_FLAGS_NOTIFY_LOGINS;
-				client->SimpleMessage(CHANNEL_COLOR_GUILD_MSGS, "Guild online notifications are now disabled.");
+				client->SimpleMessage(CHANNEL_GUILD_CHAT, "Guild online notifications are now disabled.");
 				ret = true;
 				ret = true;
 			}
 			}
 			break;
 			break;
@@ -1284,12 +1284,12 @@ bool Guild::ChangeMemberFlag(Client *client, int8 member_flag, int8 value, bool
 		case GUILD_MEMBER_FLAGS_DONT_GENERATE_EVENTS: {
 		case GUILD_MEMBER_FLAGS_DONT_GENERATE_EVENTS: {
 			if (value > 1 && !(gm->member_flags & GUILD_MEMBER_FLAGS_DONT_GENERATE_EVENTS)) {
 			if (value > 1 && !(gm->member_flags & GUILD_MEMBER_FLAGS_DONT_GENERATE_EVENTS)) {
 				gm->member_flags += GUILD_MEMBER_FLAGS_DONT_GENERATE_EVENTS;
 				gm->member_flags += GUILD_MEMBER_FLAGS_DONT_GENERATE_EVENTS;
-				client->SimpleMessage(CHANNEL_COLOR_GUILD_MSGS, "Guild events are now disabled for this character.");
+				client->SimpleMessage(CHANNEL_GUILD_CHAT, "Guild events are now disabled for this character.");
 				ret = true;
 				ret = true;
 			}
 			}
 			else if (value == 0 && gm->member_flags & GUILD_MEMBER_FLAGS_DONT_GENERATE_EVENTS) {
 			else if (value == 0 && gm->member_flags & GUILD_MEMBER_FLAGS_DONT_GENERATE_EVENTS) {
 				gm->member_flags -= GUILD_MEMBER_FLAGS_DONT_GENERATE_EVENTS;
 				gm->member_flags -= GUILD_MEMBER_FLAGS_DONT_GENERATE_EVENTS;
-				client->SimpleMessage(CHANNEL_COLOR_GUILD_MSGS, "Guild events are now enabled for this character.");
+				client->SimpleMessage(CHANNEL_GUILD_CHAT, "Guild events are now enabled for this character.");
 				ret = true;
 				ret = true;
 			}
 			}
 			break;
 			break;
@@ -1499,7 +1499,7 @@ int8 Guild::GetRecruitingLookingForPacketValue() {
 void Guild::SendGuildMOTD(Client* client) {
 void Guild::SendGuildMOTD(Client* client) {
 
 
 	if (client && strlen(motd) > 0)
 	if (client && strlen(motd) > 0)
-		client->Message(CHANNEL_COLOR_GUILD_MOTD, "Guild MOTD: %s", motd);
+		client->Message(CHANNEL_GUILD_MOTD, "Guild MOTD: %s", motd);
 
 
 	LogWrite(GUILD__DEBUG, 1, "Guilds", "Sent guild MOTD.\n'%s'", motd);
 	LogWrite(GUILD__DEBUG, 1, "Guilds", "Sent guild MOTD.\n'%s'", motd);
 }
 }
@@ -2201,7 +2201,7 @@ void Guild::HandleGuildSay(Client* sender, const char* message) {
 		return;
 		return;
 
 
 	if (!permissions.Get(gm->rank)->Get(GUILD_PERMISSIONS_SPEAK_IN_GUILD_CHAT)) {
 	if (!permissions.Get(gm->rank)->Get(GUILD_PERMISSIONS_SPEAK_IN_GUILD_CHAT)) {
-		sender->SimpleMessage(CHANNEL_COLOR_WHITE, "You do not have permission to speak in guild chat.");
+		sender->SimpleMessage(CHANNEL_NARRATIVE, "You do not have permission to speak in guild chat.");
 		return;
 		return;
 	}
 	}
 
 
@@ -2211,7 +2211,7 @@ void Guild::HandleGuildSay(Client* sender, const char* message) {
 			continue;
 			continue;
 			
 			
 		if (permissions.Get(itr->second->rank)->Get(GUILD_PERMISSIONS_SEE_GUILD_CHAT))
 		if (permissions.Get(itr->second->rank)->Get(GUILD_PERMISSIONS_SEE_GUILD_CHAT))
-			client->GetCurrentZone()->HandleChatMessage(client, sender->GetPlayer(), client->GetPlayer()->GetName(), CHANNEL_GUILD, message, 0, 0, false);
+			client->GetCurrentZone()->HandleChatMessage(client, sender->GetPlayer(), client->GetPlayer()->GetName(), CHANNEL_GUILD_SAY, message, 0, 0, false);
 	}
 	}
 	mMembers.releasereadlock(__FUNCTION__, __LINE__);
 	mMembers.releasereadlock(__FUNCTION__, __LINE__);
 	LogWrite(GUILD__DEBUG, 0, "Guilds", "Guild Say");
 	LogWrite(GUILD__DEBUG, 0, "Guilds", "Guild Say");
@@ -2230,7 +2230,7 @@ void Guild::HandleOfficerSay(Client* sender, const char* message) {
 		return;
 		return;
 
 
 	if (!permissions.Get(gm->rank)->Get(GUILD_PERMISSIONS_SPEAK_IN_OFFICER_CHAT)) {
 	if (!permissions.Get(gm->rank)->Get(GUILD_PERMISSIONS_SPEAK_IN_OFFICER_CHAT)) {
-		sender->SimpleMessage(CHANNEL_COLOR_WHITE, "You do not have permission to speak in officer chat.");
+		sender->SimpleMessage(CHANNEL_NARRATIVE, "You do not have permission to speak in officer chat.");
 		return;
 		return;
 	}
 	}
 				
 				
@@ -2240,7 +2240,7 @@ void Guild::HandleOfficerSay(Client* sender, const char* message) {
 			continue;
 			continue;
 
 
 		if (permissions.Get(itr->second->rank)->Get(GUILD_PERMISSIONS_SEE_OFFICER_CHAT))
 		if (permissions.Get(itr->second->rank)->Get(GUILD_PERMISSIONS_SEE_OFFICER_CHAT))
-			client->GetCurrentZone()->HandleChatMessage(client, sender->GetPlayer(), client->GetPlayer()->GetName(), CHANNEL_OFFICER, message, 0, 0, false);
+			client->GetCurrentZone()->HandleChatMessage(client, sender->GetPlayer(), client->GetPlayer()->GetName(), CHANNEL_OFFICER_SAY, message, 0, 0, false);
 	}
 	}
 	mMembers.releasereadlock(__FUNCTION__, __LINE__);
 	mMembers.releasereadlock(__FUNCTION__, __LINE__);
 	LogWrite(GUILD__DEBUG, 0, "Guilds", "Officer Say");
 	LogWrite(GUILD__DEBUG, 0, "Guilds", "Officer Say");
@@ -2263,7 +2263,7 @@ void Guild::SendMessageToGuild(int8 event_type, const char* message, ...) {
 			continue;
 			continue;
 
 
 		if (event_filters.Get(itr->second->rank)->Get(GUILD_EVENT_FILTER_CATEGORY_BROADCAST))
 		if (event_filters.Get(itr->second->rank)->Get(GUILD_EVENT_FILTER_CATEGORY_BROADCAST))
-			client->SimpleMessage(CHANNEL_COLOR_GUILD_EVENT, buffer);
+			client->SimpleMessage(CHANNEL_GUILD_EVENT, buffer);
 	}
 	}
 	mMembers.releasereadlock(__FUNCTION__, __LINE__);
 	mMembers.releasereadlock(__FUNCTION__, __LINE__);
 	LogWrite(GUILD__DEBUG, 0, "Guilds", "Sent message to entire guild.");
 	LogWrite(GUILD__DEBUG, 0, "Guilds", "Sent message to entire guild.");

+ 17 - 3
EQ2/source/WorldServer/Items/Items.cpp

@@ -763,6 +763,8 @@ Item::Item(Item* in_item){
 	save_needed = true;
 	save_needed = true;
 	SetItem(in_item);
 	SetItem(in_item);
 	details.unique_id = master_item_list.NextUniqueID();
 	details.unique_id = master_item_list.NextUniqueID();
+	if (IsBag())
+		details.bag_id = details.unique_id;
 	generic_info.condition = 100;
 	generic_info.condition = 100;
 	spell_id = in_item->spell_id;
 	spell_id = in_item->spell_id;
 	spell_tier = in_item->spell_tier;
 	spell_tier = in_item->spell_tier;
@@ -1499,6 +1501,8 @@ void Item::serialize(PacketStruct* packet, bool show_name, Player* player, int16
 	}
 	}
 	if(show_name)
 	if(show_name)
 		packet->setSubstructSubstructDataByName("header", "info_header", "show_name", show_name);
 		packet->setSubstructSubstructDataByName("header", "info_header", "show_name", show_name);
+	if (packet_type == 20)
+		cout << "";
 	if(packet_type == 0)
 	if(packet_type == 0)
 		packet->setSubstructSubstructDataByName("header", "info_header", "packettype", GetItemPacketType(packet->GetVersion()));
 		packet->setSubstructSubstructDataByName("header", "info_header", "packettype", GetItemPacketType(packet->GetVersion()));
 	else
 	else
@@ -3423,8 +3427,11 @@ bool EquipmentItemList::AddItem(int8 slot, Item* item){
 	if(item){
 	if(item){
 		MEquipmentItems.lock();
 		MEquipmentItems.lock();
 		SetItem(slot, item);
 		SetItem(slot, item);
-		if(item->details.unique_id == 0)
+		if (item->details.unique_id == 0) {
 			GetItem(slot)->details.unique_id = MasterItemList::NextUniqueID();
 			GetItem(slot)->details.unique_id = MasterItemList::NextUniqueID();
+			if (item->IsBag())
+				item->details.bag_id = item->details.unique_id;
+		}
 		MEquipmentItems.unlock();
 		MEquipmentItems.unlock();
 		return true;
 		return true;
 	}
 	}
@@ -3682,8 +3689,15 @@ int8 EquipmentItemList::GetSlotByItem(Item* item) {
 	return slot;
 	return slot;
 }
 }
 
 
-string Item::CreateItemLink(bool bUseUniqueID) {
+string Item::CreateItemLink(int16 client_Version, bool bUseUniqueID) {
 	ostringstream ss;
 	ostringstream ss;
-	ss << "\\aITEM " << details.item_id << ' ' << (bUseUniqueID ? details.unique_id : 0) << ':' << name << "\\/a";
+	if(client_Version > 546)
+		ss << "\\aITEM " << details.item_id << ' ' << (bUseUniqueID ? details.unique_id : 0) << ':' << name << "\\/a";
+	else {
+		if(bUseUniqueID)
+			ss << "\\aITEM " << details.item_id << ' ' << details.unique_id << ':' << name << "\\/a";
+		else
+			ss << "\\aITEM " << details.item_id << ' ' << name << ':' << name << "\\/a";
+	}
 	return ss.str();
 	return ss.str();
 }
 }

+ 1 - 2
EQ2/source/WorldServer/Items/Items.h

@@ -845,7 +845,6 @@ public:
 	int32					spell_id;
 	int32					spell_id;
 	int8					spell_tier;
 	int8					spell_tier;
 	string					item_script;
 	string					item_script;
-
 	void AddEffect(string effect, int8 percentage, int8 subbulletflag);
 	void AddEffect(string effect, int8 percentage, int8 subbulletflag);
 	void AddBookPage(int8 page, string page_text,int8 valign, int8 halign);
 	void AddBookPage(int8 page, string page_text,int8 valign, int8 halign);
 	int32 GetMaxSellValue();
 	int32 GetMaxSellValue();
@@ -910,7 +909,7 @@ public:
 	void SetItemScript(string name);
 	void SetItemScript(string name);
 	const char*	GetItemScript();
 	const char*	GetItemScript();
 	int32 CalculateRepairCost();
 	int32 CalculateRepairCost();
-	string CreateItemLink(bool bUseUniqueID);
+	string CreateItemLink(int16 client_Version, bool bUseUniqueID=false);
 
 
 	void SetItemType(int8 in_type);
 	void SetItemType(int8 in_type);
 	void serialize(PacketStruct* packet, bool show_name = false, Player* player = 0, int16 packet_type = 0, int8 subtype = 0, bool loot_item = false);
 	void serialize(PacketStruct* packet, bool show_name = false, Player* player = 0, int16 packet_type = 0, int8 subtype = 0, bool loot_item = false);

+ 505 - 48
EQ2/source/WorldServer/LuaFunctions.cpp

@@ -36,7 +36,9 @@
 #include "ClientPacketFunctions.h"
 #include "ClientPacketFunctions.h"
 #include "Transmute.h"
 #include "Transmute.h"
 #include <boost/algorithm/string/predicate.hpp>
 #include <boost/algorithm/string/predicate.hpp>
+#include <sstream> 
 
 
+extern MasterFactionList master_faction_list;
 extern WorldDatabase database;
 extern WorldDatabase database;
 extern LuaInterface* lua_interface;
 extern LuaInterface* lua_interface;
 extern ConfigReader configReader;
 extern ConfigReader configReader;
@@ -54,6 +56,98 @@ extern MasterHeroicOPList master_ho_list;
 extern MasterRaceTypeList race_types_list;
 extern MasterRaceTypeList race_types_list;
 extern MasterLanguagesList master_languages_list;
 extern MasterLanguagesList master_languages_list;
 
 
+vector<string> ParseString(string strVal, char delim) {
+	stringstream ss(strVal);
+	vector<string> ret;
+	while (ss.good())
+	{
+		string substr;
+		getline(ss, substr, delim);
+		ret.push_back(substr);
+	}
+	return ret;
+}
+
+vector<unsigned int> ParseStringToInt32(string strVal, char delim) {
+	stringstream ss(strVal);
+	vector<unsigned int> ret;
+	while (ss.good())
+	{
+		string substr;
+		getline(ss, substr, delim);
+		stringstream valss(substr);
+		unsigned int val = 0;
+		valss >> val;
+		ret.push_back(val);
+	}
+	return ret;
+}
+
+map<string, signed  int> ParseStringMap(string strVal, char delim) {
+	vector<string> pairs = ParseString(strVal, delim);
+	vector<string>::iterator itr;
+	map<string, signed int> ret;
+	for (itr = pairs.begin(); itr != pairs.end(); itr++) {
+		vector<string> keyvaluepair = ParseString(*itr, ':');
+		if (keyvaluepair.size() == 2) {
+			stringstream valss(keyvaluepair[1]);
+			int32 val = 0;
+			valss >> val;
+			ret[keyvaluepair[0]] = val;
+		}
+	}	
+	
+	return ret;
+}
+
+map<unsigned int, unsigned short> ParseIntMap(string strVal, char delim) {
+	vector<string> pairs = ParseString(strVal, delim);
+	vector<string>::iterator itr;
+	map<unsigned int, unsigned short> ret;
+	for (itr = pairs.begin(); itr != pairs.end(); itr++) {
+		vector<string> keyvaluepair = ParseString(*itr, ':');
+		int32 key = 0;
+		if (keyvaluepair.size() > 0) {
+			stringstream keyss(keyvaluepair[0]);
+			keyss >> key;
+		}
+		if (keyvaluepair.size() == 1) {
+			ret[key] = 1;
+		}
+		else if (keyvaluepair.size() == 2) {
+			stringstream valss(keyvaluepair[1]);
+			unsigned short val = 0;
+			valss >> val;
+			ret[key] = val;
+		}
+	}
+	return ret;
+}
+
+map<unsigned int, signed int> ParseSInt32Map(string strVal, char delim) {
+	vector<string> pairs = ParseString(strVal, delim);
+	vector<string>::iterator itr;
+	map<unsigned int, signed int> ret;
+	for (itr = pairs.begin(); itr != pairs.end(); itr++) {
+		vector<string> keyvaluepair = ParseString(*itr, ':');
+		int32 key = 0;
+		if (keyvaluepair.size() > 0) {
+			stringstream keyss(keyvaluepair[0]);
+			keyss >> key;
+		}
+		if (keyvaluepair.size() == 1) {
+			ret[key] = 1;
+		}
+		else if (keyvaluepair.size() == 2) {
+			stringstream valss(keyvaluepair[1]);
+			signed int val = 0;
+			valss >> val;
+			ret[key] = val;
+		}
+	}
+	return ret;
+}
+
 int EQ2Emu_lua_PlayFlavor(lua_State* state) {
 int EQ2Emu_lua_PlayFlavor(lua_State* state) {
 	if (!lua_interface)
 	if (!lua_interface)
 		return 0;
 		return 0;
@@ -230,6 +324,29 @@ int EQ2Emu_lua_Despawn(lua_State* state) {
 	return 0;
 	return 0;
 }
 }
 
 
+int EQ2Emu_lua_ChangeHandIcon(lua_State* state) {
+	if (!lua_interface)
+		return 0;
+	Spawn* spawn = lua_interface->GetSpawn(state);
+	int8 displayHandIcon = lua_interface->GetInt8Value(state, 2);
+	if (spawn) {
+		spawn->info_changed = true;
+		spawn->SetShowHandIcon(displayHandIcon);
+	}
+	return 0;
+}
+
+int EQ2Emu_lua_SendStateCommand(lua_State* state) {
+	if (!lua_interface)
+		return 0;
+	Spawn* spawn = lua_interface->GetSpawn(state);
+	int32 new_state = lua_interface->GetInt32Value(state, 2);
+	if (spawn) {
+		spawn->GetZone()->SendStateCommand(spawn, new_state);
+	}
+	return 0;
+}
+
 int EQ2Emu_lua_SpawnSet(lua_State* state) {
 int EQ2Emu_lua_SpawnSet(lua_State* state) {
 	if (!lua_interface)
 	if (!lua_interface)
 		return 0;
 		return 0;
@@ -257,6 +374,88 @@ int EQ2Emu_lua_GetSpawn(lua_State* state) {
 	return 0;
 	return 0;
 }
 }
 
 
+int EQ2Emu_lua_GetSpawnFromList(lua_State* state) {
+	if (!lua_interface)
+		return 0;
+	vector<Spawn*>* spawnList = lua_interface->GetSpawnList(state);
+	int32 position = lua_interface->GetInt32Value(state, 2);
+	if (spawnList) {
+		if (spawnList->size() > position) {
+			lua_interface->SetSpawnValue(state, spawnList->at(position));
+			return 1;
+		}
+		else {
+			return 0;
+		}
+		return spawnList->size();
+	}
+	return 0;
+}
+
+int EQ2Emu_lua_GetSpawnListSize(lua_State* state) {
+	if (!lua_interface)
+		return 0;
+	vector<Spawn*>* spawnList = lua_interface->GetSpawnList(state);
+	if (spawnList) {
+		return spawnList->size();
+	}
+	return 0;
+}
+
+int EQ2Emu_lua_CreateSpawnList(lua_State* state) {
+	if (!lua_interface)
+		return 0;
+	vector<Spawn*>* spawnList = new vector<Spawn*>();
+	lua_interface->SetSpawnListValue(state, spawnList);
+	return 1;
+}
+
+int EQ2Emu_lua_AddSpawnToSpawnList(lua_State* state) {
+	if (!lua_interface)
+		return 0;
+	vector<Spawn*>* spawnList = lua_interface->GetSpawnList(state);
+	Spawn* spawn = lua_interface->GetSpawn(state, 2);
+	if (spawnList) {
+		auto it = std::find(spawnList->begin(), spawnList->end(), spawn);
+		if (it == spawnList->end())
+			spawnList->push_back(spawn);
+	}
+	return 0;
+}
+
+int EQ2Emu_lua_RemoveSpawnFromSpawnList(lua_State* state) {
+	if (!lua_interface)
+		return 0;
+	vector<Spawn*>* spawnList = lua_interface->GetSpawnList(state);
+	Spawn* spawn = lua_interface->GetSpawn(state, 2);
+	if (spawnList) {
+		auto it = std::find(spawnList->begin(), spawnList->end(), spawn);
+		if(it != spawnList->end())
+			spawnList->erase(it);
+	}
+	return 0;
+}
+
+int EQ2Emu_lua_GetSpawnListBySpawnID(lua_State* state) {
+	if (!lua_interface)
+		return 0;
+	Spawn* spawn = lua_interface->GetSpawn(state);
+	int32 spawn_id = lua_interface->GetInt32Value(state, 2);
+	if (spawn) {
+		vector<Spawn*> spawns = spawn->GetZone()->GetSpawnsByID(spawn_id);
+		if (spawns.size() > 0) {
+			vector<Spawn*>* spawnList = new vector<Spawn*>();
+			vector<Spawn*>::iterator itr;
+			for (itr = spawns.begin(); itr != spawns.end(); itr++) {
+				spawnList->push_back(*itr);
+			}
+			lua_interface->SetSpawnListValue(state, spawnList);
+			return 1;
+		}
+	}
+	return 0;
+}
+
 int EQ2Emu_lua_GetVariableValue(lua_State* state) {
 int EQ2Emu_lua_GetVariableValue(lua_State* state) {
 	if (!lua_interface)
 	if (!lua_interface)
 		return 0;
 		return 0;
@@ -455,6 +654,18 @@ int EQ2Emu_lua_GetCurrentZoneSafeLocation(lua_State* state) {
 	return 0;
 	return 0;
 }
 }
 
 
+int EQ2Emu_lua_HasLootItem(lua_State* state) {
+	if (!lua_interface)
+		return 0;
+	Spawn* spawn = lua_interface->GetSpawn(state);
+	if (spawn) {
+		int32 item_id = lua_interface->GetInt32Value(state, 2);
+		lua_interface->SetBooleanValue(state, spawn->HasLootItemID(item_id));
+		return 1;
+	}
+	return 0;
+}
+
 int EQ2Emu_lua_AddLootItem(lua_State* state) {
 int EQ2Emu_lua_AddLootItem(lua_State* state) {
 	if (!lua_interface)
 	if (!lua_interface)
 		return 0;
 		return 0;
@@ -484,9 +695,9 @@ int EQ2Emu_lua_AddLootCoin(lua_State* state) {
 	if (!lua_interface)
 	if (!lua_interface)
 		return 0;
 		return 0;
 	Spawn* spawn = lua_interface->GetSpawn(state);
 	Spawn* spawn = lua_interface->GetSpawn(state);
-	if (spawn && spawn->IsEntity()) {
+	if (spawn) {
 		int32 val = lua_interface->GetInt32Value(state, 2);
 		int32 val = lua_interface->GetInt32Value(state, 2);
-		((Entity*)spawn)->AddLootCoins(val);
+		spawn->AddLootCoins(val);
 	}
 	}
 	return 0;
 	return 0;
 }
 }
@@ -509,11 +720,11 @@ int EQ2Emu_lua_GiveLoot(lua_State* state) {
 			i++;
 			i++;
 		}
 		}
 		Client* client = 0;
 		Client* client = 0;
-		client = entity->GetZone()->GetClientBySpawn(player);
-		if (client) {
+		client = player->GetZone()->GetClientBySpawn(player);
+		if (client) 
 			((Player*)player)->AddPendingLootItems(entity->GetID(), items);
 			((Player*)player)->AddPendingLootItems(entity->GetID(), items);
-			client->Loot(coins, ((Player*)player)->GetPendingLootItems(entity->GetID()), (Entity*)entity);
-		}
+		if(coins > 0)
+			entity->AddLootCoins(coins);
 		safe_delete(items);
 		safe_delete(items);
 	}
 	}
 	return 0;
 	return 0;
@@ -537,7 +748,7 @@ int EQ2Emu_lua_HasPendingLoot(lua_State* state) {
 		return 0;
 		return 0;
 	Spawn* entity = lua_interface->GetSpawn(state);
 	Spawn* entity = lua_interface->GetSpawn(state);
 	Spawn* player = lua_interface->GetSpawn(state, 2);
 	Spawn* player = lua_interface->GetSpawn(state, 2);
-	if (entity && entity->IsEntity() && player && player->IsPlayer()) {
+	if (entity && player && player->IsPlayer()) {
 		lua_interface->SetBooleanValue(state, ((Player*)player)->HasPendingLootItems(entity->GetID()));
 		lua_interface->SetBooleanValue(state, ((Player*)player)->HasPendingLootItems(entity->GetID()));
 		return 1;
 		return 1;
 	}
 	}
@@ -800,6 +1011,16 @@ int EQ2Emu_lua_MoveToLocation(lua_State* state) {
 	return 0;
 	return 0;
 }
 }
 
 
+int EQ2Emu_lua_ClearRunningLocations(lua_State* state) {
+	if (!lua_interface)
+		return 0;
+	Spawn* spawn = lua_interface->GetSpawn(state);
+	if (spawn) {
+		spawn->ClearRunningLocations();
+	}
+	return 0;
+}
+
 int EQ2Emu_lua_Say(lua_State* state) {
 int EQ2Emu_lua_Say(lua_State* state) {
 	if (!lua_interface)
 	if (!lua_interface)
 		return 0;
 		return 0;
@@ -850,9 +1071,9 @@ int EQ2Emu_lua_SayOOC(lua_State* state) {
 		if (player && player->IsPlayer())
 		if (player && player->IsPlayer())
 			client = spawn->GetZone()->GetClientBySpawn(player);
 			client = spawn->GetZone()->GetClientBySpawn(player);
 		if (client)
 		if (client)
-			spawn->GetZone()->HandleChatMessage(client, spawn, 0, CHANNEL_OOC, message.c_str(), 30);
+			spawn->GetZone()->HandleChatMessage(client, spawn, 0, CHANNEL_OUT_OF_CHARACTER, message.c_str(), 30);
 		else
 		else
-			spawn->GetZone()->HandleChatMessage(spawn, 0, CHANNEL_OOC, message.c_str(), 30);
+			spawn->GetZone()->HandleChatMessage(spawn, 0, CHANNEL_OUT_OF_CHARACTER, message.c_str(), 30);
 	}
 	}
 	lua_interface->ResetFunctionStack(state);
 	lua_interface->ResetFunctionStack(state);
 	return 0;
 	return 0;
@@ -967,7 +1188,7 @@ int EQ2Emu_lua_SummonItem(lua_State* state) {
 			if (send_messages) {
 			if (send_messages) {
 				Item* item = master_item_list.GetItem(item_id);
 				Item* item = master_item_list.GetItem(item_id);
 				if (item) {
 				if (item) {
-					client->Message(CHANNEL_COLOR_YELLOW, "You receive \\aITEM %u 0:%s\\/a.", item->details.item_id, item->name.c_str());
+					client->Message(CHANNEL_COLOR_YELLOW, "You receive %s.", item->CreateItemLink(client->GetVersion()).c_str());
 					string popup_text = "You receive " + item->name;
 					string popup_text = "You receive " + item->name;
 					client->SendPopupMessage(10, popup_text.c_str(), "ui_harvested_normal", 3, 0xFF, 0xFF, 0xFF);
 					client->SendPopupMessage(10, popup_text.c_str(), "ui_harvested_normal", 3, 0xFF, 0xFF, 0xFF);
 				}
 				}
@@ -1068,7 +1289,7 @@ int EQ2Emu_lua_Spawn(lua_State* state) {
 			output = output.append("\t").append("Missing zone reference. \n");
 			output = output.append("\t").append("Missing zone reference. \n");
 		if (spawn_id == 0)
 		if (spawn_id == 0)
 			output = output.append("\t").append("Missing spawn_id.");
 			output = output.append("\t").append("Missing spawn_id.");
-		lua_interface->LogError("%s: Error in EQ2Emu_lua_Zone - %s", lua_interface->GetScriptName(state), output.c_str());
+		lua_interface->LogError("%s: Error in EQ2Emu_lua_Spawn - %s", lua_interface->GetScriptName(state), output.c_str());
 	}
 	}
 	return 0;
 	return 0;
 }
 }
@@ -2835,6 +3056,7 @@ int EQ2Emu_lua_OfferQuest(lua_State* state) {
 	Spawn* npc = lua_interface->GetSpawn(state);
 	Spawn* npc = lua_interface->GetSpawn(state);
 	Spawn* player = lua_interface->GetSpawn(state, 2);
 	Spawn* player = lua_interface->GetSpawn(state, 2);
 	int32 quest_id = lua_interface->GetInt32Value(state, 3);
 	int32 quest_id = lua_interface->GetInt32Value(state, 3);
+	bool forced = lua_interface->GetBooleanValue(state, 4);
 
 
 	/* NPC is allowed to be null */
 	/* NPC is allowed to be null */
 	if (player && player->IsPlayer() && quest_id > 0) {
 	if (player && player->IsPlayer() && quest_id > 0) {
@@ -2842,12 +3064,12 @@ int EQ2Emu_lua_OfferQuest(lua_State* state) {
 		if (master_quest) {
 		if (master_quest) {
 			Client* client = player->GetZone()->GetClientBySpawn(player);
 			Client* client = player->GetZone()->GetClientBySpawn(player);
 			Quest* quest = new Quest(master_quest);
 			Quest* quest = new Quest(master_quest);
-			if (client && quest) {
-				client->AddPendingQuest(quest);
+			if (client && quest) {				
 				if (npc)
 				if (npc)
 					quest->SetQuestGiver(npc->GetDatabaseID());
 					quest->SetQuestGiver(npc->GetDatabaseID());
 				else
 				else
 					quest->SetQuestGiver(0);
 					quest->SetQuestGiver(0);
+				client->AddPendingQuest(quest, forced);
 			}
 			}
 		}
 		}
 	}
 	}
@@ -3074,6 +3296,10 @@ int EQ2Emu_lua_AddQuestStepKill(lua_State* state) {
 		QuestStep* quest_step = quest->AddQuestStep(step, QUEST_STEP_TYPE_KILL, description, ids, quantity, taskgroup, 0, 0, percentage, 0);
 		QuestStep* quest_step = quest->AddQuestStep(step, QUEST_STEP_TYPE_KILL, description, ids, quantity, taskgroup, 0, 0, percentage, 0);
 		if (quest_step && icon > 0 && quantity > 0)
 		if (quest_step && icon > 0 && quantity > 0)
 			quest_step->SetIcon(icon);
 			quest_step->SetIcon(icon);
+		if (quest->GetPlayer()) {
+			Client* client = quest->GetPlayer()->GetZone()->GetClientBySpawn(quest->GetPlayer());
+			quest->GetPlayer()->GetZone()->SendQuestUpdates(client);
+		}
 	}
 	}
 	return 0;
 	return 0;
 }
 }
@@ -3137,6 +3363,10 @@ int EQ2Emu_lua_AddQuestStepObtainItem(lua_State* state) {
 		QuestStep* quest_step = quest->AddQuestStep(step, QUEST_STEP_TYPE_OBTAIN_ITEM, description, ids, quantity, taskgroup, 0, 0, percentage, 0);
 		QuestStep* quest_step = quest->AddQuestStep(step, QUEST_STEP_TYPE_OBTAIN_ITEM, description, ids, quantity, taskgroup, 0, 0, percentage, 0);
 		if (quest_step && icon > 0 && quantity > 0)
 		if (quest_step && icon > 0 && quantity > 0)
 			quest_step->SetIcon(icon);
 			quest_step->SetIcon(icon);
+		if (quest->GetPlayer()) {
+			Client* client = quest->GetPlayer()->GetZone()->GetClientBySpawn(quest->GetPlayer());
+			quest->GetPlayer()->GetZone()->SendQuestUpdates(client);
+		}
 	}
 	}
 	return 0;
 	return 0;
 }
 }
@@ -3171,6 +3401,10 @@ int EQ2Emu_lua_AddQuestStepLocation(lua_State* state) {
 		QuestStep* quest_step = quest->AddQuestStep(step, QUEST_STEP_TYPE_LOCATION, description, 0, 1, taskgroup, locations, max_variation);
 		QuestStep* quest_step = quest->AddQuestStep(step, QUEST_STEP_TYPE_LOCATION, description, 0, 1, taskgroup, locations, max_variation);
 		if (quest_step && icon > 0)
 		if (quest_step && icon > 0)
 			quest_step->SetIcon(icon);
 			quest_step->SetIcon(icon);
+		if (quest->GetPlayer()) {
+			Client* client = quest->GetPlayer()->GetZone()->GetClientBySpawn(quest->GetPlayer());
+			quest->GetPlayer()->GetZone()->SendQuestUpdates(client);
+		}
 	}
 	}
 	return 0;
 	return 0;
 }
 }
@@ -3204,6 +3438,10 @@ int EQ2Emu_lua_AddQuestUsableItem(lua_State* state) {
 		QuestStep* quest_step = quest->AddQuestStep(step, QUEST_STEP_TYPE_LOCATION, description, 0, 1, taskgroup, locations, max_variation);
 		QuestStep* quest_step = quest->AddQuestStep(step, QUEST_STEP_TYPE_LOCATION, description, 0, 1, taskgroup, locations, max_variation);
 		if (quest_step && icon > 0)
 		if (quest_step && icon > 0)
 			quest_step->SetIcon(icon);
 			quest_step->SetIcon(icon);
+		if (quest->GetPlayer()) {
+			Client* client = quest->GetPlayer()->GetZone()->GetClientBySpawn(quest->GetPlayer());
+			quest->GetPlayer()->GetZone()->SendQuestUpdates(client);
+		}
 	}
 	}
 	return 0;
 	return 0;
 }
 }
@@ -3231,6 +3469,10 @@ int EQ2Emu_lua_AddQuestStepSpell(lua_State* state) {
 		QuestStep* quest_step = quest->AddQuestStep(step, QUEST_STEP_TYPE_SPELL, description, ids, quantity, taskgroup, 0, 0, percentage, 0);
 		QuestStep* quest_step = quest->AddQuestStep(step, QUEST_STEP_TYPE_SPELL, description, ids, quantity, taskgroup, 0, 0, percentage, 0);
 		if (quest_step && icon > 0 && quantity > 0)
 		if (quest_step && icon > 0 && quantity > 0)
 			quest_step->SetIcon(icon);
 			quest_step->SetIcon(icon);
+		if (quest->GetPlayer()) {
+			Client* client = quest->GetPlayer()->GetZone()->GetClientBySpawn(quest->GetPlayer());
+			quest->GetPlayer()->GetZone()->SendQuestUpdates(client);
+		}
 	}
 	}
 	return 0;
 	return 0;
 }
 }
@@ -3261,6 +3503,10 @@ int EQ2Emu_lua_AddQuestStepCraft(lua_State* state) {
 		QuestStep* quest_step = quest->AddQuestStep(step, QUEST_STEP_TYPE_CRAFT, description, ids, quantity, taskgroup, 0, 0, percentage, 0);
 		QuestStep* quest_step = quest->AddQuestStep(step, QUEST_STEP_TYPE_CRAFT, description, ids, quantity, taskgroup, 0, 0, percentage, 0);
 		if (quest_step && icon > 0 && quantity > 0)
 		if (quest_step && icon > 0 && quantity > 0)
 			quest_step->SetIcon(icon);
 			quest_step->SetIcon(icon);
+		if (quest->GetPlayer()) {
+			Client* client = quest->GetPlayer()->GetZone()->GetClientBySpawn(quest->GetPlayer());
+			quest->GetPlayer()->GetZone()->SendQuestUpdates(client);
+		}
 	}
 	}
 	return 0;
 	return 0;
 }
 }
@@ -3291,6 +3537,10 @@ int EQ2Emu_lua_AddQuestStepHarvest(lua_State* state) {
 		QuestStep* quest_step = quest->AddQuestStep(step, QUEST_STEP_TYPE_HARVEST, description, ids, quantity, taskgroup, 0, 0, percentage, 0);
 		QuestStep* quest_step = quest->AddQuestStep(step, QUEST_STEP_TYPE_HARVEST, description, ids, quantity, taskgroup, 0, 0, percentage, 0);
 		if (quest_step && icon > 0 && quantity > 0)
 		if (quest_step && icon > 0 && quantity > 0)
 			quest_step->SetIcon(icon);
 			quest_step->SetIcon(icon);
+		if (quest->GetPlayer()) {
+			Client* client = quest->GetPlayer()->GetZone()->GetClientBySpawn(quest->GetPlayer());
+			quest->GetPlayer()->GetZone()->SendQuestUpdates(client);
+		}
 	}
 	}
 	return 0;
 	return 0;
 }
 }
@@ -3382,7 +3632,7 @@ int EQ2Emu_lua_UpdateQuestStepDescription(lua_State* state) {
 		if (quest->GetPlayer()) {
 		if (quest->GetPlayer()) {
 			Client* client = quest->GetPlayer()->GetZone()->GetClientBySpawn(quest->GetPlayer());
 			Client* client = quest->GetPlayer()->GetZone()->GetClientBySpawn(quest->GetPlayer());
 			if (client)
 			if (client)
-				client->SendQuestUpdateStep(quest, step);
+				client->SendQuestUpdateStepImmediately(quest, step);
 		}
 		}
 	}
 	}
 	return 0;
 	return 0;
@@ -3396,6 +3646,148 @@ int EQ2Emu_lua_UpdateQuestZone(lua_State* state) {
 	return 0;
 	return 0;
 }
 }
 
 
+int EQ2Emu_lua_GiveImmediateQuestReward(lua_State* state) {
+	if (!lua_interface)
+		return 0;
+	Quest* quest = lua_interface->GetQuest(state);
+	Spawn* playerSpawn = lua_interface->GetSpawn(state, 2);
+	int32 coin = lua_interface->GetInt32Value(state, 3);
+	int32 status_points = lua_interface->GetInt32Value(state, 4);	
+	string rewards_str = lua_interface->GetStringValue(state, 5);
+	string select_rewards_str = lua_interface->GetStringValue(state, 6);
+	string factions_map_str = lua_interface->GetStringValue(state, 7);
+	string text = lua_interface->GetStringValue(state, 8);
+	int32 source_id = 0;
+	if (quest)
+		source_id = quest->GetQuestID();
+	if (playerSpawn && playerSpawn->IsPlayer()) {
+		Player* player = (Player*)playerSpawn;
+		Client* client = player->GetZone()->GetClientBySpawn(player);
+		if (client) {
+			vector<Item*> reward_items;
+			vector<Item*> selectable_reward_items;
+			if (rewards_str.length() > 0) {
+				map<unsigned int, unsigned short> rewards = ParseIntMap(rewards_str);
+				map<unsigned int, unsigned short>::iterator itr;
+				for (itr = rewards.begin(); itr != rewards.end(); itr++) {
+					if (itr->first > 0) {
+						Item* item = new Item(master_item_list.GetItem(itr->first));
+						if (item) {
+							if (itr->second > 0)
+								item->stack_count = itr->second;
+							reward_items.push_back(item);
+						}
+					}
+				}
+			}
+			if (select_rewards_str.length() > 0) {
+				map<unsigned int, unsigned short> rewards = ParseIntMap(select_rewards_str);
+				map<unsigned int, unsigned short>::iterator itr;
+				for (itr = rewards.begin(); itr != rewards.end(); itr++) {
+					if (itr->first > 0) {
+						Item* item = new Item(master_item_list.GetItem(itr->first));
+						if (item) {
+							if (itr->second > 0)
+								item->stack_count = itr->second;
+							selectable_reward_items.push_back(item);
+						}
+					}
+				}
+			}
+			map<unsigned int, signed int> faction_rewards = ParseSInt32Map(factions_map_str);
+			const char* reward_type = "Quest Reward!";
+			if (!quest)
+				reward_type = "Reward!";
+			client->DisplayQuestRewards(0, coin, &reward_items, &selectable_reward_items, &faction_rewards, reward_type, status_points, text.c_str());
+		}
+	}
+			/*PacketStruct* packet2 = configReader.getStruct("WS_QuestRewardPackMsg", client->GetVersion());
+			if (packet2) {
+				player->AddCoins(coin);
+				client->PlaySound("coin_cha_ching");
+				packet2->setSubstructDataByName("reward_data", "unknown1", 255);
+				if(quest)
+					packet2->setSubstructDataByName("reward_data", "reward", "Quest Reward!");
+				else
+					packet2->setSubstructDataByName("reward_data", "reward", "Reward!");
+				packet2->setSubstructDataByName("reward_data", "coin", coin);
+				if (player->GetGuild()) {
+					player->GetInfoStruct()->status_points += status_points;
+					packet2->setSubstructDataByName("reward_data", "status_points", status_points);
+				}
+				if (rewards_str.length() > 0) {
+					map<unsigned int, unsigned short> rewards = ParseIntMap(rewards_str);
+					vector<Item*> reward_items;
+					map<unsigned int, unsigned short>::iterator itr;
+					for (itr = rewards.begin(); itr != rewards.end(); itr++) {
+						if (itr->first > 0) {
+							Item* item = new Item(master_item_list.GetItem(itr->first));
+							if (item) {
+								if (itr->second > 0)
+									item->stack_count = itr->second;
+								reward_items.push_back(item);
+							}
+						}
+					}
+					packet2->setSubstructArrayLengthByName("reward_data", "num_rewards", reward_items.size());
+					for (int i = 0; i < reward_items.size(); i++) {
+						Item* item = reward_items[i];
+						packet2->setArrayDataByName("reward_id", item->details.item_id, i);
+						packet2->setItemArrayDataByName("item", item, client->GetPlayer(), i, 0, -1);
+						player->AddPendingItemReward(item); //item reference will be deleted after the player accepts it
+					}
+				}
+				if (select_rewards_str.length() > 0) {
+					map<unsigned int, unsigned short> rewards = ParseIntMap(select_rewards_str);
+					vector<Item*> reward_items;
+					map<unsigned int, unsigned short>::iterator itr;
+					for (itr = rewards.begin(); itr != rewards.end(); itr++) {
+						if (itr->first > 0) {
+							Item* item = new Item(master_item_list.GetItem(itr->first));
+							if (item) {
+								if (itr->second > 0)
+									item->stack_count = itr->second;
+								reward_items.push_back(item);
+							}
+						}
+					}
+					packet2->setSubstructArrayLengthByName("reward_data", "num_select_rewards", reward_items.size());
+					for (int i = 0; i < reward_items.size(); i++) {
+						Item* item = reward_items[i];
+						packet2->setArrayDataByName("select_reward_id", item->details.item_id, i);
+						packet2->setItemArrayDataByName("select_item", item, client->GetPlayer(), i, 0, -1);
+						player->AddPendingSelectableItemReward(source_id, item); //item reference will be deleted after the player selects one
+					}
+				}
+				if (factions_map_str.length() > 0) {
+					map<unsigned int, signed int> faction_rewards = ParseSInt32Map(factions_map_str);
+					map<unsigned int, signed int>::iterator itr;
+					map<Faction*, signed int> factions;
+					for (itr = faction_rewards.begin(); itr != faction_rewards.end(); itr++) {
+						Faction* faction = master_faction_list.GetFaction(itr->first);
+						if (faction)
+							factions[faction] = itr->second;
+					}
+					packet2->setSubstructArrayLengthByName("reward_data", "num_factions", factions.size());
+					map<Faction*, signed int>::iterator faction_itr;
+					int8 i = 0;
+					for (faction_itr = factions.begin(); faction_itr != factions.end(); faction_itr++) {
+						packet2->setArrayDataByName("faction_name", faction_itr->first->name.c_str(), i);
+						sint32 amount = faction_itr->second;
+						packet2->setArrayDataByName("amount", amount, i);
+						if (amount > 0)
+							player->GetFactions()->IncreaseFaction(faction_itr->first->id, amount);
+						else
+							player->GetFactions()->DecreaseFaction(faction_itr->first->id, (amount * -1));
+						i++;
+					}
+				}				
+				client->QueuePacket(packet2->serialize());
+				safe_delete(packet2);
+			}*/
+	return 0;
+}
+
 int EQ2Emu_lua_GiveQuestReward(lua_State* state) {
 int EQ2Emu_lua_GiveQuestReward(lua_State* state) {
 	if (!lua_interface)
 	if (!lua_interface)
 		return 0;
 		return 0;
@@ -3549,7 +3941,7 @@ int EQ2Emu_lua_SendMessage(lua_State* state) {
 	Spawn* spawn = lua_interface->GetSpawn(state);
 	Spawn* spawn = lua_interface->GetSpawn(state);
 	string message = lua_interface->GetStringValue(state, 2);
 	string message = lua_interface->GetStringValue(state, 2);
 	string color_str = lua_interface->GetStringValue(state, 3);
 	string color_str = lua_interface->GetStringValue(state, 3);
-	int8 color = CHANNEL_COLOR_WHITE;
+	int8 color = CHANNEL_NARRATIVE;
 	if (spawn && spawn->IsPlayer() && message.length() > 0) {
 	if (spawn && spawn->IsPlayer() && message.length() > 0) {
 		Client* client = spawn->GetZone()->GetClientBySpawn(spawn);
 		Client* client = spawn->GetZone()->GetClientBySpawn(spawn);
 		if (client) {
 		if (client) {
@@ -4086,6 +4478,18 @@ int EQ2Emu_lua_SetTradeskillLevel(lua_State* state) {
 	return 0;
 	return 0;
 }
 }
 
 
+int EQ2Emu_lua_SetAttackable(lua_State* state) {
+	if (!lua_interface)
+		return 0;
+	Spawn* spawn = lua_interface->GetSpawn(state);
+	int8 attackable = lua_interface->GetInt8Value(state, 2);
+	if (spawn) {		
+		spawn->SetAttackable(attackable);
+		spawn->vis_changed = true; //some clients store this in vis instead of info, need to make sense both are updated
+	}
+	return 0;
+}
+
 int EQ2Emu_lua_SummonPet(lua_State* state) {
 int EQ2Emu_lua_SummonPet(lua_State* state) {
 	// Check to see if we have a valid lua_interface
 	// Check to see if we have a valid lua_interface
 	if (!lua_interface)
 	if (!lua_interface)
@@ -4941,7 +5345,7 @@ int EQ2Emu_lua_GiveQuestItem(lua_State* state)
 		safe_delete(packet);
 		safe_delete(packet);
 
 
 		lua_interface->SetBooleanValue(state, client->AddItem(item_id, 1));
 		lua_interface->SetBooleanValue(state, client->AddItem(item_id, 1));
-		client->Message(CHANNEL_COLOR_YELLOW, "You receive \\aITEM %u 0:%s\\/a.", item->details.item_id, item->name.c_str());
+		client->Message(CHANNEL_COLOR_YELLOW, "You receive %s.", item->CreateItemLink(client->GetVersion()).c_str());
 		return 1;
 		return 1;
 	}
 	}
 
 
@@ -9350,6 +9754,22 @@ int EQ2Emu_lua_AddLootToObject(lua_State* state) {
 	return 0;
 	return 0;
 }
 }
 
 
+int EQ2Emu_lua_GiveExp(lua_State* state) {
+	if (!lua_interface)
+		return 0;
+	Spawn* player = lua_interface->GetSpawn(state);
+	int32 amount = lua_interface->GetInt32Value(state, 2);
+	if (player && player->IsPlayer() && amount > 0) {
+		((Player*)player)->AddXP(amount);
+		((Player*)player)->SetCharSheetChanged(true);
+		Client* client = player->GetZone()->GetClientBySpawn(player);
+		if (client) {
+			client->SimpleMessage(CHANNEL_REWARD, "You gain experience!");
+		}
+	}
+	return 0;
+}
+
 int EQ2Emu_lua_DisplayText(lua_State* state) {
 int EQ2Emu_lua_DisplayText(lua_State* state) {
 	if (!lua_interface)
 	if (!lua_interface)
 		return 0;
 		return 0;
@@ -9384,32 +9804,7 @@ int EQ2Emu_lua_ShowLootWindow(lua_State* state) {
 		lua_interface->LogError("%s: LUA ShowLootWindow has no items", lua_interface->GetScriptName(state));
 		lua_interface->LogError("%s: LUA ShowLootWindow has no items", lua_interface->GetScriptName(state));
 		return 0;
 		return 0;
 	}
 	}
-	client->Loot(0, items, spawn);
-	/*PacketStruct* packet2 = configReader.getStruct("WS_UpdateLoot", client->GetVersion());
-	if (packet2) {
-		packet2->setArrayLengthByName("loot_count", items->size());
-		for(int i=0;i< items->size();i++){
-			Item* item = (*items)[0];
-			packet2->setArrayDataByName("name", item->name.c_str(), i);
-			packet2->setArrayDataByName("item_id", item->details.item_id, i);
-			packet2->setArrayDataByName("count", item->details.count, i);
-			packet2->setArrayDataByName("icon", item->details.icon, i);
-			if(item->generic_info.skill_req1 > 0 && item->generic_info.skill_req1 < 0xFFFFFFFF)
-				packet2->setArrayDataByName("ability_id", item->generic_info.skill_req1, i);
-			else if (item->generic_info.skill_req2 > 0 && item->generic_info.skill_req2 < 0xFFFFFFFF)
-				packet2->setArrayDataByName("ability_id", item->generic_info.skill_req2, i);
-			else
-				packet2->setArrayDataByName("ability_id", 0xFFFFFFFF, i);
-		}
-		packet2->setDataByName("object_id", spawn->GetID());
-		packet2->setDataByName("unknown3", 1);
-		packet2->setDataByName("unknown4", 1);
-		packet2->setDataByName("unknown5", 60);
-		EQ2Packet* app = packet2->serialize();
-		DumpPacket(app);
-		client->QueuePacket(app);
-		safe_delete(packet2);
-	}*/
+	client->Loot(spawn->GetLootCoins(), items, spawn);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -9471,6 +9866,46 @@ int EQ2Emu_lua_AddPrimaryEntityCommandAllSpawns(lua_State* state) {
 	return 0;
 	return 0;
 }
 }
 
 
+int EQ2Emu_lua_InstructionWindowGoal(lua_State* state) {
+	if (!lua_interface)
+		return 0;
+	Client* client = 0;
+	Spawn* player = lua_interface->GetSpawn(state);
+	int8 goal_num = lua_interface->GetInt8Value(state, 2);
+	if (player && player->IsPlayer() && player->GetZone())
+		client = player->GetZone()->GetClientBySpawn(player);
+	else{
+		lua_interface->LogError("LUA InstructionWindowGoal command error: player is not valid");
+		return 0;
+	}
+	if (client) {
+		PacketStruct* packet = configReader.getStruct("WS_InstructionWindow", client->GetVersion());
+		if (packet) {
+			packet->setDataByName("goal_num", goal_num);
+			client->QueuePacket(packet->serialize());
+			safe_delete(packet);
+		}
+	}
+	return 0;
+}
+
+int EQ2Emu_lua_InstructionWindowClose(lua_State* state) {
+	if (!lua_interface)
+		return 0;
+	Client* client = 0;
+	Spawn* player = lua_interface->GetSpawn(state);
+	if (player && player->IsPlayer() && player->GetZone())
+		client = player->GetZone()->GetClientBySpawn(player);
+	else {
+		lua_interface->LogError("LUA InstructionWindowClose command error: player is not valid");
+		return 0;
+	}
+	if (client) {
+		client->QueuePacket(new EQ2Packet(OP_EqInstructionWindowCloseCmd, 0, 0));
+	}
+	return 0;
+}
+
 int EQ2Emu_lua_InstructionWindow(lua_State* state) {
 int EQ2Emu_lua_InstructionWindow(lua_State* state) {
 	if (!lua_interface)
 	if (!lua_interface)
 		return 0;
 		return 0;
@@ -9499,8 +9934,8 @@ int EQ2Emu_lua_InstructionWindow(lua_State* state) {
 		lua_interface->LogError("LUA InstructionWindow command error: spawn is not a player");
 		lua_interface->LogError("LUA InstructionWindow command error: spawn is not a player");
 		return 0;
 		return 0;
 	}
 	}
-	if (player->GetZone())
-		client = player->GetZone()->GetClientBySpawn(player);
+	else
+		client = ((Player*)player)->GetClient();
 
 
 	if (!client) {
 	if (!client) {
 		lua_interface->LogError("LUA InstructionWindow command error: could not find client");
 		lua_interface->LogError("LUA InstructionWindow command error: could not find client");
@@ -9568,8 +10003,8 @@ int EQ2Emu_lua_ShowWindow(lua_State* state) {
 		lua_interface->LogError("LUA ShowWindow command error: spawn is not a player");
 		lua_interface->LogError("LUA ShowWindow command error: spawn is not a player");
 		return 0;
 		return 0;
 	}
 	}
-	if (player->GetZone())
-		client = player->GetZone()->GetClientBySpawn(player);
+	else
+		client = ((Player*)player)->GetClient();
 
 
 	if (!client) {
 	if (!client) {
 		lua_interface->LogError("LUA ShowWindow command error: could not find client");
 		lua_interface->LogError("LUA ShowWindow command error: could not find client");
@@ -9618,6 +10053,28 @@ int EQ2Emu_lua_EnableGameEvent(lua_State* state) {
 	return 0;
 	return 0;
 }
 }
 
 
+int EQ2Emu_lua_GetTutorialStep(lua_State* state) {
+	if (!lua_interface)
+		return 0;
+	Spawn* player = lua_interface->GetSpawn(state);
+	if (player && player->IsPlayer()) {
+		lua_interface->SetInt32Value(state, ((Player*)player)->GetTutorialStep());
+		return 1;
+	}
+	return 0;
+}
+
+int EQ2Emu_lua_SetTutorialStep(lua_State* state) {
+	if (!lua_interface)
+		return 0;
+	Spawn* player = lua_interface->GetSpawn(state);
+	int8 step = lua_interface->GetInt8Value(state, 2);
+	if (player && player->IsPlayer() && step > 0) {
+		((Player*)player)->SetTutorialStep(step);
+	}
+	return 0;
+}
+
 int EQ2Emu_lua_FlashWindow(lua_State* state) {
 int EQ2Emu_lua_FlashWindow(lua_State* state) {
 	if (!lua_interface)
 	if (!lua_interface)
 		return 0;
 		return 0;
@@ -9633,8 +10090,8 @@ int EQ2Emu_lua_FlashWindow(lua_State* state) {
 		lua_interface->LogError("LUA FlashWindow command error: spawn is not a player");
 		lua_interface->LogError("LUA FlashWindow command error: spawn is not a player");
 		return 0;
 		return 0;
 	}
 	}
-	if (player->GetZone())
-		client = player->GetZone()->GetClientBySpawn(player);
+	else
+		client = ((Player*)player)->GetClient();
 
 
 	if (!client) {
 	if (!client) {
 		lua_interface->LogError("LUA FlashWindow command error: could not find client");
 		lua_interface->LogError("LUA FlashWindow command error: could not find client");

+ 28 - 0
EQ2/source/WorldServer/LuaFunctions.h

@@ -21,6 +21,17 @@
 #define LUA_FUNCTIONS_H
 #define LUA_FUNCTIONS_H
 
 
 #include "../LUA/lua.hpp"
 #include "../LUA/lua.hpp"
+#include <vector>
+#include <string>
+#include <map>
+using namespace std;
+
+vector<string> ParseString(string strVal, char delim=',');
+vector<unsigned int> ParseStringToInt32(string strVal, char delim=',');
+map<string, signed int> ParseStringMap(string strVal, char delim=',');
+map<unsigned int, unsigned short> ParseIntMap(string strVal, char delim = ',');
+map<unsigned int, signed int> ParseSInt32Map(string strVal, char delim = ',');
+
 
 
 //Sets
 //Sets
 int EQ2Emu_lua_SetCurrentHP(lua_State* state);
 int EQ2Emu_lua_SetCurrentHP(lua_State* state);
@@ -91,6 +102,12 @@ int EQ2Emu_lua_GetStrBase(lua_State* state);
 int EQ2Emu_lua_GetAgiBase(lua_State* state);
 int EQ2Emu_lua_GetAgiBase(lua_State* state);
 int EQ2Emu_lua_GetLootCoin(lua_State* state);
 int EQ2Emu_lua_GetLootCoin(lua_State* state);
 int EQ2Emu_lua_GetSpawn(lua_State* state);
 int EQ2Emu_lua_GetSpawn(lua_State* state);
+int EQ2Emu_lua_GetSpawnFromList(lua_State* state);
+int EQ2Emu_lua_GetSpawnListSize(lua_State* state);
+int EQ2Emu_lua_CreateSpawnList(lua_State* state);
+int EQ2Emu_lua_AddSpawnToSpawnList(lua_State* state);
+int EQ2Emu_lua_RemoveSpawnFromSpawnList(lua_State* state);
+int EQ2Emu_lua_GetSpawnListBySpawnID(lua_State* state); 
 int EQ2Emu_lua_GetVariableValue(lua_State* state);
 int EQ2Emu_lua_GetVariableValue(lua_State* state);
 int EQ2Emu_lua_GetCoinMessage(lua_State* state);
 int EQ2Emu_lua_GetCoinMessage(lua_State* state);
 int EQ2Emu_lua_GetSpawnByGroupID(lua_State* state);
 int EQ2Emu_lua_GetSpawnByGroupID(lua_State* state);
@@ -113,6 +130,8 @@ int EQ2Emu_lua_GetItemType(lua_State* state);
 int EQ2Emu_lua_GetSpellName(lua_State* state);
 int EQ2Emu_lua_GetSpellName(lua_State* state);
 
 
 //Misc
 //Misc
+int EQ2Emu_lua_SetAttackable(lua_State* state);
+int EQ2Emu_lua_SendStateCommand(lua_State* state);
 int EQ2Emu_lua_SpawnSet(lua_State* state);
 int EQ2Emu_lua_SpawnSet(lua_State* state);
 int EQ2Emu_lua_KillSpawn(lua_State* state); 
 int EQ2Emu_lua_KillSpawn(lua_State* state); 
 int EQ2Emu_lua_KillSpawnByDistance(lua_State* state);
 int EQ2Emu_lua_KillSpawnByDistance(lua_State* state);
@@ -120,6 +139,7 @@ int EQ2Emu_lua_SpawnSetByDistance(lua_State* state);
 int EQ2Emu_lua_SetRequiredQuest(lua_State* state);
 int EQ2Emu_lua_SetRequiredQuest(lua_State* state);
 int EQ2Emu_lua_SetRequiredHistory(lua_State* state);
 int EQ2Emu_lua_SetRequiredHistory(lua_State* state);
 int EQ2Emu_lua_Despawn(lua_State* state);
 int EQ2Emu_lua_Despawn(lua_State* state);
+int EQ2Emu_lua_ChangeHandIcon(lua_State* state);
 int EQ2Emu_lua_AddHate(lua_State* state);
 int EQ2Emu_lua_AddHate(lua_State* state);
 int EQ2Emu_lua_GetZone(lua_State* state);
 int EQ2Emu_lua_GetZone(lua_State* state);
 int EQ2Emu_lua_GetZoneName(lua_State* state);
 int EQ2Emu_lua_GetZoneName(lua_State* state);
@@ -141,6 +161,7 @@ int EQ2Emu_lua_CastSpell(lua_State* state);
 int EQ2Emu_lua_SpellDamage(lua_State* state);
 int EQ2Emu_lua_SpellDamage(lua_State* state);
 int EQ2Emu_lua_FaceTarget(lua_State* state);
 int EQ2Emu_lua_FaceTarget(lua_State* state);
 int EQ2Emu_lua_MoveToLocation(lua_State* state);
 int EQ2Emu_lua_MoveToLocation(lua_State* state);
+int EQ2Emu_lua_ClearRunningLocations(lua_State* state);
 int EQ2Emu_lua_Say(lua_State* state);
 int EQ2Emu_lua_Say(lua_State* state);
 int EQ2Emu_lua_Shout(lua_State* state);
 int EQ2Emu_lua_Shout(lua_State* state);
 int EQ2Emu_lua_SayOOC(lua_State* state);
 int EQ2Emu_lua_SayOOC(lua_State* state);
@@ -153,6 +174,7 @@ int EQ2Emu_lua_PlaySound(lua_State* state);
 int EQ2Emu_lua_PlayVoice(lua_State* state);
 int EQ2Emu_lua_PlayVoice(lua_State* state);
 int EQ2Emu_lua_PlayAnimation(lua_State* state);
 int EQ2Emu_lua_PlayAnimation(lua_State* state);
 int EQ2Emu_lua_AddLootItem(lua_State* state);
 int EQ2Emu_lua_AddLootItem(lua_State* state);
+int EQ2Emu_lua_HasLootItem(lua_State* state);
 int EQ2Emu_lua_RemoveLootItem(lua_State* state);
 int EQ2Emu_lua_RemoveLootItem(lua_State* state);
 int EQ2Emu_lua_AddLootCoin(lua_State* state);
 int EQ2Emu_lua_AddLootCoin(lua_State* state);
 int EQ2Emu_lua_GiveLoot(lua_State* state);
 int EQ2Emu_lua_GiveLoot(lua_State* state);
@@ -229,6 +251,7 @@ int EQ2Emu_lua_AddQuestStepCompleteAction(lua_State* state);
 int EQ2Emu_lua_AddQuestStepProgressAction(lua_State* state);
 int EQ2Emu_lua_AddQuestStepProgressAction(lua_State* state);
 int EQ2Emu_lua_SetQuestCompleteAction(lua_State* state);
 int EQ2Emu_lua_SetQuestCompleteAction(lua_State* state);
 int EQ2Emu_lua_GiveQuestReward(lua_State* state);
 int EQ2Emu_lua_GiveQuestReward(lua_State* state);
+int EQ2Emu_lua_GiveImmediateQuestReward(lua_State* state);
 int EQ2Emu_lua_UpdateQuestTaskGroupDescription(lua_State* state);
 int EQ2Emu_lua_UpdateQuestTaskGroupDescription(lua_State* state);
 int EQ2Emu_lua_UpdateQuestStepDescription(lua_State* state);
 int EQ2Emu_lua_UpdateQuestStepDescription(lua_State* state);
 int EQ2Emu_lua_UpdateQuestDescription(lua_State* state);
 int EQ2Emu_lua_UpdateQuestDescription(lua_State* state);
@@ -417,14 +440,19 @@ int EQ2Emu_lua_StartTransmute(lua_State* state);
 int EQ2Emu_lua_CompleteTransmute(lua_State* state);
 int EQ2Emu_lua_CompleteTransmute(lua_State* state);
 int EQ2Emu_lua_ProcHate(lua_State* state);
 int EQ2Emu_lua_ProcHate(lua_State* state);
 
 
+int EQ2Emu_lua_GiveExp(lua_State* state);
 int EQ2Emu_lua_DisplayText(lua_State* state);
 int EQ2Emu_lua_DisplayText(lua_State* state);
 int EQ2Emu_lua_ShowLootWindow(lua_State* state);
 int EQ2Emu_lua_ShowLootWindow(lua_State* state);
 int EQ2Emu_lua_GetRandomSpawnByID(lua_State* state);
 int EQ2Emu_lua_GetRandomSpawnByID(lua_State* state);
 int EQ2Emu_lua_AddPrimaryEntityCommandAllSpawns(lua_State* state);
 int EQ2Emu_lua_AddPrimaryEntityCommandAllSpawns(lua_State* state);
 int EQ2Emu_lua_InstructionWindow(lua_State* state);
 int EQ2Emu_lua_InstructionWindow(lua_State* state);
+int EQ2Emu_lua_InstructionWindowClose(lua_State* state);
+int EQ2Emu_lua_InstructionWindowGoal(lua_State* state);
 int EQ2Emu_lua_ShowWindow(lua_State* state);
 int EQ2Emu_lua_ShowWindow(lua_State* state);
 int EQ2Emu_lua_FlashWindow(lua_State* state);
 int EQ2Emu_lua_FlashWindow(lua_State* state);
 int EQ2Emu_lua_EnableGameEvent(lua_State* state);
 int EQ2Emu_lua_EnableGameEvent(lua_State* state);
+int EQ2Emu_lua_GetTutorialStep(lua_State* state);
+int EQ2Emu_lua_SetTutorialStep(lua_State* state);
 
 
 int EQ2Emu_lua_CheckLOS(lua_State* state);
 int EQ2Emu_lua_CheckLOS(lua_State* state);
 int EQ2Emu_lua_CheckLOSByCoordinates(lua_State* state);
 int EQ2Emu_lua_CheckLOSByCoordinates(lua_State* state);

+ 80 - 7
EQ2/source/WorldServer/LuaInterface.cpp

@@ -696,6 +696,12 @@ void LuaInterface::RegisterFunctions(lua_State* state) {
 	lua_register(state, "GetSpawnGroupID", EQ2Emu_lua_GetSpawnGroupID);
 	lua_register(state, "GetSpawnGroupID", EQ2Emu_lua_GetSpawnGroupID);
 	lua_register(state, "GetSpawnLocationID", EQ2Emu_lua_GetSpawnLocationID);
 	lua_register(state, "GetSpawnLocationID", EQ2Emu_lua_GetSpawnLocationID);
 	lua_register(state, "GetSpawnLocationPlacementID", EQ2Emu_lua_GetSpawnLocationPlacementID);
 	lua_register(state, "GetSpawnLocationPlacementID", EQ2Emu_lua_GetSpawnLocationPlacementID);
+	lua_register(state, "CreateSpawnList", EQ2Emu_lua_CreateSpawnList);
+	lua_register(state, "AddSpawnToSpawnList", EQ2Emu_lua_AddSpawnToSpawnList);
+	lua_register(state, "RemoveSpawnFromSpawnList", EQ2Emu_lua_RemoveSpawnFromSpawnList);
+	lua_register(state, "GetSpawnListBySpawnID", EQ2Emu_lua_GetSpawnListBySpawnID);
+	lua_register(state, "GetSpawnFromList", EQ2Emu_lua_GetSpawnFromList);
+	lua_register(state, "GetSpawnListSize", EQ2Emu_lua_GetSpawnListSize);	
 	lua_register(state, "SetFactionID", EQ2Emu_lua_SetFactionID);
 	lua_register(state, "SetFactionID", EQ2Emu_lua_SetFactionID);
 	lua_register(state, "GetFactionID", EQ2Emu_lua_GetFactionID);
 	lua_register(state, "GetFactionID", EQ2Emu_lua_GetFactionID);
 	lua_register(state, "GetFactionAmount", EQ2Emu_lua_GetFactionAmount);
 	lua_register(state, "GetFactionAmount", EQ2Emu_lua_GetFactionAmount);
@@ -735,14 +741,17 @@ void LuaInterface::RegisterFunctions(lua_State* state) {
 	lua_register(state, "IsPlayer", EQ2Emu_lua_IsPlayer);
 	lua_register(state, "IsPlayer", EQ2Emu_lua_IsPlayer);
 	lua_register(state, "FaceTarget", EQ2Emu_lua_FaceTarget);
 	lua_register(state, "FaceTarget", EQ2Emu_lua_FaceTarget);
 	lua_register(state, "MoveToLocation", EQ2Emu_lua_MoveToLocation);
 	lua_register(state, "MoveToLocation", EQ2Emu_lua_MoveToLocation);
+	lua_register(state, "ClearRunningLocations", EQ2Emu_lua_ClearRunningLocations);
 	lua_register(state, "Shout", EQ2Emu_lua_Shout);
 	lua_register(state, "Shout", EQ2Emu_lua_Shout);
 	lua_register(state, "Say", EQ2Emu_lua_Say);
 	lua_register(state, "Say", EQ2Emu_lua_Say);
 	lua_register(state, "SayOOC", EQ2Emu_lua_SayOOC);
 	lua_register(state, "SayOOC", EQ2Emu_lua_SayOOC);
 	lua_register(state, "Emote", EQ2Emu_lua_Emote);
 	lua_register(state, "Emote", EQ2Emu_lua_Emote);
-	lua_register(state, "MovementLoopAddLocation", EQ2Emu_lua_MovementLoopAdd);
+	lua_register(state, "MovementLoopAdd", EQ2Emu_lua_MovementLoopAdd);
 	lua_register(state, "GetCurrentZoneSafeLocation", EQ2Emu_lua_GetCurrentZoneSafeLocation);
 	lua_register(state, "GetCurrentZoneSafeLocation", EQ2Emu_lua_GetCurrentZoneSafeLocation);
 	lua_register(state, "AddTimer", EQ2Emu_lua_AddTimer);
 	lua_register(state, "AddTimer", EQ2Emu_lua_AddTimer);
 	lua_register(state, "Harvest", EQ2Emu_lua_Harvest);
 	lua_register(state, "Harvest", EQ2Emu_lua_Harvest);
+	lua_register(state, "SetAttackable", EQ2Emu_lua_SetAttackable);
+
 	
 	
 	lua_register(state, "AddSpellBonus", EQ2Emu_lua_AddSpellBonus);
 	lua_register(state, "AddSpellBonus", EQ2Emu_lua_AddSpellBonus);
 	lua_register(state, "RemoveSpellBonus", EQ2Emu_lua_RemoveSpellBonus);
 	lua_register(state, "RemoveSpellBonus", EQ2Emu_lua_RemoveSpellBonus);
@@ -781,6 +790,7 @@ void LuaInterface::RegisterFunctions(lua_State* state) {
 	lua_register(state, "PlayVoice", EQ2Emu_lua_PlayVoice);
 	lua_register(state, "PlayVoice", EQ2Emu_lua_PlayVoice);
 	lua_register(state, "PlayAnimation", EQ2Emu_lua_PlayAnimation);
 	lua_register(state, "PlayAnimation", EQ2Emu_lua_PlayAnimation);
 	lua_register(state, "AddLootItem", EQ2Emu_lua_AddLootItem);
 	lua_register(state, "AddLootItem", EQ2Emu_lua_AddLootItem);
+	lua_register(state, "HasLootItem", EQ2Emu_lua_HasLootItem);
 	lua_register(state, "RemoveLootItem", EQ2Emu_lua_RemoveLootItem);
 	lua_register(state, "RemoveLootItem", EQ2Emu_lua_RemoveLootItem);
 	lua_register(state, "AddLootCoin", EQ2Emu_lua_AddLootCoin);
 	lua_register(state, "AddLootCoin", EQ2Emu_lua_AddLootCoin);
 	lua_register(state, "GiveLoot", EQ2Emu_lua_GiveLoot);
 	lua_register(state, "GiveLoot", EQ2Emu_lua_GiveLoot);
@@ -796,13 +806,15 @@ void LuaInterface::RegisterFunctions(lua_State* state) {
 	lua_register(state, "CloseConversation", EQ2Emu_lua_CloseConversation);
 	lua_register(state, "CloseConversation", EQ2Emu_lua_CloseConversation);
 	lua_register(state, "CloseItemConversation", EQ2Emu_lua_CloseItemConversation);
 	lua_register(state, "CloseItemConversation", EQ2Emu_lua_CloseItemConversation);
 	//lua_register(state, "StartItemConversation", EQ2Emu_lua_StartItemConversation);
 	//lua_register(state, "StartItemConversation", EQ2Emu_lua_StartItemConversation);
-	lua_register(state, "StartDialogConversation", EQ2Emu_lua_StartDialogConversation);
+	lua_register(state, "StartDialogConversation", EQ2Emu_lua_StartDialogConversation);	
+	lua_register(state, "SendStateCommand", EQ2Emu_lua_SendStateCommand);
 	lua_register(state, "SpawnSet", EQ2Emu_lua_SpawnSet);
 	lua_register(state, "SpawnSet", EQ2Emu_lua_SpawnSet);
 	lua_register(state, "SpawnSetByDistance", EQ2Emu_lua_SpawnSetByDistance);
 	lua_register(state, "SpawnSetByDistance", EQ2Emu_lua_SpawnSetByDistance);
 	lua_register(state, "SpawnMove", EQ2Emu_lua_SpawnMove);
 	lua_register(state, "SpawnMove", EQ2Emu_lua_SpawnMove);
 	lua_register(state, "KillSpawn", EQ2Emu_lua_KillSpawn); 
 	lua_register(state, "KillSpawn", EQ2Emu_lua_KillSpawn); 
 	lua_register(state, "KillSpawnByDistance", EQ2Emu_lua_KillSpawnByDistance);
 	lua_register(state, "KillSpawnByDistance", EQ2Emu_lua_KillSpawnByDistance);
 	lua_register(state, "Despawn", EQ2Emu_lua_Despawn);
 	lua_register(state, "Despawn", EQ2Emu_lua_Despawn);
+	lua_register(state, "ChangeHandIcon", EQ2Emu_lua_ChangeHandIcon);
 	lua_register(state, "IsBindAllowed", EQ2Emu_lua_IsBindAllowed);
 	lua_register(state, "IsBindAllowed", EQ2Emu_lua_IsBindAllowed);
 	lua_register(state, "IsGateAllowed", EQ2Emu_lua_IsGateAllowed);
 	lua_register(state, "IsGateAllowed", EQ2Emu_lua_IsGateAllowed);
 	lua_register(state, "Bind", EQ2Emu_lua_Bind);
 	lua_register(state, "Bind", EQ2Emu_lua_Bind);
@@ -858,6 +870,7 @@ void LuaInterface::RegisterFunctions(lua_State* state) {
 	lua_register(state, "AddQuestStepProgressAction", EQ2Emu_lua_AddQuestStepProgressAction);
 	lua_register(state, "AddQuestStepProgressAction", EQ2Emu_lua_AddQuestStepProgressAction);
 	lua_register(state, "SetQuestCompleteAction", EQ2Emu_lua_SetQuestCompleteAction);
 	lua_register(state, "SetQuestCompleteAction", EQ2Emu_lua_SetQuestCompleteAction);
 	lua_register(state, "GiveQuestReward", EQ2Emu_lua_GiveQuestReward);
 	lua_register(state, "GiveQuestReward", EQ2Emu_lua_GiveQuestReward);
+	lua_register(state, "GiveImmediateQuestReward", EQ2Emu_lua_GiveImmediateQuestReward);
 	lua_register(state, "UpdateQuestStepDescription", EQ2Emu_lua_UpdateQuestStepDescription);
 	lua_register(state, "UpdateQuestStepDescription", EQ2Emu_lua_UpdateQuestStepDescription);
 	lua_register(state, "UpdateQuestDescription", EQ2Emu_lua_UpdateQuestDescription);
 	lua_register(state, "UpdateQuestDescription", EQ2Emu_lua_UpdateQuestDescription);
 	lua_register(state, "UpdateQuestZone", EQ2Emu_lua_UpdateQuestZone);
 	lua_register(state, "UpdateQuestZone", EQ2Emu_lua_UpdateQuestZone);
@@ -1045,10 +1058,15 @@ void LuaInterface::RegisterFunctions(lua_State* state) {
 	lua_register(state, "ShowLootWindow", EQ2Emu_lua_ShowLootWindow);
 	lua_register(state, "ShowLootWindow", EQ2Emu_lua_ShowLootWindow);
 	lua_register(state, "AddPrimaryEntityCommandAllSpawns", EQ2Emu_lua_AddPrimaryEntityCommandAllSpawns);
 	lua_register(state, "AddPrimaryEntityCommandAllSpawns", EQ2Emu_lua_AddPrimaryEntityCommandAllSpawns);
 	lua_register(state, "InstructionWindow", EQ2Emu_lua_InstructionWindow);
 	lua_register(state, "InstructionWindow", EQ2Emu_lua_InstructionWindow);
+	lua_register(state, "InstructionWindowClose", EQ2Emu_lua_InstructionWindowClose);
+	lua_register(state, "InstructionWindowGoal", EQ2Emu_lua_InstructionWindowGoal);
 	lua_register(state, "ShowWindow", EQ2Emu_lua_ShowWindow);
 	lua_register(state, "ShowWindow", EQ2Emu_lua_ShowWindow);
 	lua_register(state, "FlashWindow", EQ2Emu_lua_FlashWindow);
 	lua_register(state, "FlashWindow", EQ2Emu_lua_FlashWindow);
 	lua_register(state, "EnableGameEvent", EQ2Emu_lua_EnableGameEvent);
 	lua_register(state, "EnableGameEvent", EQ2Emu_lua_EnableGameEvent);
+	lua_register(state, "GetTutorialStep", EQ2Emu_lua_GetTutorialStep);
+	lua_register(state, "SetTutorialStep", EQ2Emu_lua_SetTutorialStep);
 	lua_register(state, "DisplayText", EQ2Emu_lua_DisplayText);
 	lua_register(state, "DisplayText", EQ2Emu_lua_DisplayText);
+	lua_register(state, "GiveExp", EQ2Emu_lua_GiveExp);
 
 
 	lua_register(state, "CheckLOS", EQ2Emu_lua_CheckLOS);
 	lua_register(state, "CheckLOS", EQ2Emu_lua_CheckLOS);
 	lua_register(state, "CheckLOSByCoordinates", EQ2Emu_lua_CheckLOSByCoordinates);
 	lua_register(state, "CheckLOSByCoordinates", EQ2Emu_lua_CheckLOSByCoordinates);
@@ -1188,6 +1206,25 @@ vector<ConversationOption>*	LuaInterface::GetConversation(lua_State* state, int8
 	return ret;
 	return ret;
 }
 }
 
 
+vector<Spawn*>* LuaInterface::GetSpawnList(lua_State* state, int8 arg_num) {
+	vector<Spawn*>* ret = 0;
+	if (lua_islightuserdata(state, arg_num)) {
+		LUAUserData* data = (LUAUserData*)lua_touserdata(state, arg_num);
+		if (!data || !data->IsCorrectlyInitialized()) {
+			LogError("%s: GetSpawnList error while processing %s", GetScriptName(state), lua_tostring(state, -1));
+		}
+		else if (!data->IsSpawnList()) {
+			lua_Debug ar;
+			lua_getstack(state, 1, &ar);
+			lua_getinfo(state, "Sln", &ar);
+			LogError("%s: Invalid data type used for GetSpawnList in %s (line %d)", GetScriptName(state), ar.source, ar.currentline);
+		}
+		else
+			ret = data->spawn_list;
+	}
+	return ret;
+}
+
 vector<OptionWindowOption>*	LuaInterface::GetOptionWindow(lua_State* state, int8 arg_num) {
 vector<OptionWindowOption>*	LuaInterface::GetOptionWindow(lua_State* state, int8 arg_num) {
 	vector<OptionWindowOption>* ret = 0;
 	vector<OptionWindowOption>* ret = 0;
 	if(lua_islightuserdata(state, arg_num)){
 	if(lua_islightuserdata(state, arg_num)){
@@ -1364,6 +1401,13 @@ void LuaInterface::SetSpawnValue(lua_State* state, Spawn* spawn) {
 	lua_pushlightuserdata(state, spawn_wrapper);
 	lua_pushlightuserdata(state, spawn_wrapper);
 }
 }
 
 
+void LuaInterface::SetSpawnListValue(lua_State* state, vector<Spawn*>* spawnList) {
+	LUASpawnListWrapper* spawnList_wrapper = new LUASpawnListWrapper();
+	spawnList_wrapper->spawn_list = spawnList;
+	AddUserDataPtr(spawnList_wrapper);
+	lua_pushlightuserdata(state, spawnList_wrapper);
+}
+
 void LuaInterface::SetConversationValue(lua_State* state, vector<ConversationOption>* conversation) {
 void LuaInterface::SetConversationValue(lua_State* state, vector<ConversationOption>* conversation) {
 	LUAConversationOptionWrapper* conv_wrapper = new LUAConversationOptionWrapper();
 	LUAConversationOptionWrapper* conv_wrapper = new LUAConversationOptionWrapper();
 	conv_wrapper->conversation_options = conversation;
 	conv_wrapper->conversation_options = conversation;
@@ -1690,7 +1734,7 @@ bool LuaInterface::RunSpawnScript(string script_name, const char* function_name,
 		return false;
 		return false;
 }
 }
 
 
-bool LuaInterface::RunZoneScript(string script_name, const char* function_name, ZoneServer* zone, Spawn* spawn, int32 grid_id, const char* signal) {
+bool LuaInterface::RunZoneScript(string script_name, const char* function_name, ZoneServer* zone, Spawn* spawn, int32 int32_arg1, const char* str_arg1, Spawn* spawn_arg1, int32 int32_arg2, const char* str_arg2, Spawn* spawn_arg2) {
 	if (!zone)
 	if (!zone)
 		return false;
 		return false;
 	lua_State* state = GetZoneScript(script_name.c_str(), true, true);
 	lua_State* state = GetZoneScript(script_name.c_str(), true, true);
@@ -1716,12 +1760,28 @@ bool LuaInterface::RunZoneScript(string script_name, const char* function_name,
 			SetSpawnValue(state, spawn);
 			SetSpawnValue(state, spawn);
 			num_params++;
 			num_params++;
 		}
 		}
-		if (grid_id > 0) {
-			SetInt32Value(state, grid_id);
+		if (int32_arg1 > 0) {
+			SetInt32Value(state, int32_arg1);
+			num_params++;
+		}
+		if (str_arg1) {
+			SetStringValue(state, str_arg1);
 			num_params++;
 			num_params++;
 		}
 		}
-		if (signal) {
-			SetStringValue(state, signal);
+		if (spawn_arg1) {
+			SetSpawnValue(state, spawn_arg1);
+			num_params++;
+		}
+		if (int32_arg2 > 0) {
+			SetInt32Value(state, int32_arg2);
+			num_params++;
+		}
+		if (str_arg2) {
+			SetStringValue(state, str_arg2);
+			num_params++;
+		}
+		if (spawn_arg2) {
+			SetSpawnValue(state, spawn_arg2);
 			num_params++;
 			num_params++;
 		}
 		}
 		if (!CallZoneScript(state, num_params)) {
 		if (!CallZoneScript(state, num_params)) {
@@ -1755,6 +1815,7 @@ LUAUserData::LUAUserData(){
 	skill = 0;
 	skill = 0;
 	option_window_option = 0;
 	option_window_option = 0;
 	item = 0;
 	item = 0;
+	spawn_list = 0;
 }
 }
 
 
 bool LUAUserData::IsCorrectlyInitialized(){
 bool LUAUserData::IsCorrectlyInitialized(){
@@ -1765,6 +1826,10 @@ bool LUAUserData::IsConversationOption(){
 	return false;
 	return false;
 }
 }
 
 
+bool LUAUserData::IsSpawnList() {
+	return false;
+}
+
 bool LUAUserData::IsOptionWindow() {
 bool LUAUserData::IsOptionWindow() {
 	return false;
 	return false;
 }
 }
@@ -1797,6 +1862,14 @@ bool LUAConversationOptionWrapper::IsConversationOption(){
 	return true;
 	return true;
 }
 }
 
 
+LUASpawnListWrapper::LUASpawnListWrapper() {
+	correctly_initialized = true;
+}
+
+bool LUASpawnListWrapper::IsSpawnList() {
+	return true;
+}
+
 LUAOptionWindowWrapper::LUAOptionWindowWrapper() {
 LUAOptionWindowWrapper::LUAOptionWindowWrapper() {
 	correctly_initialized = true;
 	correctly_initialized = true;
 }
 }

+ 12 - 1
EQ2/source/WorldServer/LuaInterface.h

@@ -100,6 +100,7 @@ public:
 	virtual ~LUAUserData(){};
 	virtual ~LUAUserData(){};
 	virtual bool IsCorrectlyInitialized();
 	virtual bool IsCorrectlyInitialized();
 	virtual bool IsConversationOption();
 	virtual bool IsConversationOption();
+	virtual bool IsSpawnList();
 	virtual bool IsOptionWindow();
 	virtual bool IsOptionWindow();
 	virtual bool IsSpawn();
 	virtual bool IsSpawn();
 	virtual bool IsQuest();
 	virtual bool IsQuest();
@@ -112,6 +113,7 @@ public:
 	Spawn* spawn;
 	Spawn* spawn;
 	vector<ConversationOption>* conversation_options;
 	vector<ConversationOption>* conversation_options;
 	vector<OptionWindowOption>* option_window_option;
 	vector<OptionWindowOption>* option_window_option;
+	vector<Spawn*>* spawn_list;
 	Quest* quest;
 	Quest* quest;
 	Skill* skill;
 	Skill* skill;
 };
 };
@@ -122,6 +124,13 @@ public:
 	bool IsConversationOption();
 	bool IsConversationOption();
 };
 };
 
 
+class LUASpawnListWrapper: public LUAUserData{
+public:
+	LUASpawnListWrapper();
+	~LUASpawnListWrapper() { safe_delete(spawn_list); }
+	bool IsSpawnList();
+};
+
 class LUAOptionWindowWrapper : public LUAUserData {
 class LUAOptionWindowWrapper : public LUAUserData {
 public:
 public:
 	LUAOptionWindowWrapper();
 	LUAOptionWindowWrapper();
@@ -177,6 +186,7 @@ public:
 	ZoneServer*		GetZone(lua_State* state, int8 arg_num = 1);
 	ZoneServer*		GetZone(lua_State* state, int8 arg_num = 1);
 	Skill*			GetSkill(lua_State* state, int8 arg_num = 1);
 	Skill*			GetSkill(lua_State* state, int8 arg_num = 1);
 	vector<ConversationOption>*	GetConversation(lua_State* state, int8 arg_num = 1);
 	vector<ConversationOption>*	GetConversation(lua_State* state, int8 arg_num = 1);
+	vector<Spawn*>* GetSpawnList(lua_State* state, int8 arg_num = 1);
 	vector<OptionWindowOption>* GetOptionWindow(lua_State* state, int8 arg_num = 1);
 	vector<OptionWindowOption>* GetOptionWindow(lua_State* state, int8 arg_num = 1);
 	int8			GetInt8Value(lua_State* state, int8 arg_num = 1);
 	int8			GetInt8Value(lua_State* state, int8 arg_num = 1);
 	int16			GetInt16Value(lua_State* state, int8 arg_num = 1);
 	int16			GetInt16Value(lua_State* state, int8 arg_num = 1);
@@ -198,6 +208,7 @@ public:
 	void			SetItemValue(lua_State* state, Item* item);
 	void			SetItemValue(lua_State* state, Item* item);
 	void			SetQuestValue(lua_State* state, Quest* quest);
 	void			SetQuestValue(lua_State* state, Quest* quest);
 	void			SetZoneValue(lua_State* state, ZoneServer* zone);
 	void			SetZoneValue(lua_State* state, ZoneServer* zone);
+	void			SetSpawnListValue(lua_State* state, vector<Spawn*>* spawnList);
 	void			SetConversationValue(lua_State* state, vector<ConversationOption>* conversation);
 	void			SetConversationValue(lua_State* state, vector<ConversationOption>* conversation);
 	void			SetOptionWindowValue(lua_State* state, vector<OptionWindowOption>* optionWindow);
 	void			SetOptionWindowValue(lua_State* state, vector<OptionWindowOption>* optionWindow);
 
 
@@ -220,7 +231,7 @@ public:
 	bool			CallItemScript(lua_State* state, int8 num_parameters);
 	bool			CallItemScript(lua_State* state, int8 num_parameters);
 	bool			RunSpawnScript(string script_name, const char* function_name, Spawn* npc, Spawn* spawn = 0, const char* message = 0);
 	bool			RunSpawnScript(string script_name, const char* function_name, Spawn* npc, Spawn* spawn = 0, const char* message = 0);
 	bool			CallSpawnScript(lua_State* state, int8 num_parameters);
 	bool			CallSpawnScript(lua_State* state, int8 num_parameters);
-	bool			RunZoneScript(string script_name, const char* function_name, ZoneServer* zone, Spawn* spawn = 0, int32 grid_id = 0, const char* signal = 0);
+	bool			RunZoneScript(string script_name, const char* function_name, ZoneServer* zone, Spawn* spawn = 0, int32 int32_arg1 = 0, const char* str_arg1 = 0, Spawn* spawn_arg1 = 0, int32 int32_arg2 = 0, const char* str_arg2 = 0, Spawn* spawn_arg2 = 0);
 	bool			CallZoneScript(lua_State* state, int8 num_parameters);
 	bool			CallZoneScript(lua_State* state, int8 num_parameters);
 	void			ResetFunctionStack(lua_State* state);
 	void			ResetFunctionStack(lua_State* state);
 	void			DestroySpells();
 	void			DestroySpells();

+ 4 - 4
EQ2/source/WorldServer/NPC_AI.cpp

@@ -78,9 +78,9 @@ void Brain::Think() {
 
 
 			// Set the NPC's target to the most hated entity if it is not already.
 			// Set the NPC's target to the most hated entity if it is not already.
 			if (m_body->GetTarget() != target) {
 			if (m_body->GetTarget() != target) {
-				m_body->SetTarget(target);
-				m_body->FaceTarget(target);
+				m_body->SetTarget(target);				
 			}
 			}
+			m_body->FaceTarget(target);
 
 
 			// Check to see if the NPC has exceeded the max chase distance
 			// Check to see if the NPC has exceeded the max chase distance
 			if (run_back_distance > MAX_CHASE_DISTANCE) {
 			if (run_back_distance > MAX_CHASE_DISTANCE) {
@@ -91,9 +91,9 @@ void Brain::Think() {
 				{
 				{
 					// Target is a client so send encounter break messages
 					// Target is a client so send encounter break messages
 					if (m_body->HasSpawnGroup())
 					if (m_body->HasSpawnGroup())
-						client->SimpleMessage(CHANNEL_COLOR_WHITE, "This encounter will no longer give encounter rewards.");
+						client->SimpleMessage(CHANNEL_NARRATIVE, "This encounter will no longer give encounter rewards.");
 					else
 					else
-						client->Message(CHANNEL_COLOR_WHITE, "%s is no longer worth any experience or treasure.", m_body->GetName());
+						client->Message(CHANNEL_NARRATIVE, "%s is no longer worth any experience or treasure.", m_body->GetName());
 				}
 				}
 				// Clear the hate list for this NPC
 				// Clear the hate list for this NPC
 				ClearHate();
 				ClearHate();

+ 42 - 34
EQ2/source/WorldServer/Player.cpp

@@ -48,6 +48,7 @@ extern MasterTitlesList master_titles_list;
 extern MasterLanguagesList master_languages_list;
 extern MasterLanguagesList master_languages_list;
 
 
 Player::Player(){
 Player::Player(){
+	tutorial_step = 0;
 	char_id = 0;
 	char_id = 0;
 	group = 0;
 	group = 0;
 	appearance.pos.grid_id = 0;
 	appearance.pos.grid_id = 0;
@@ -194,6 +195,8 @@ Player::~Player(){
 	safe_delete(spawn_info_struct);
 	safe_delete(spawn_info_struct);
 	safe_delete(spawn_vis_struct);
 	safe_delete(spawn_vis_struct);
 	safe_delete(spawn_pos_struct);
 	safe_delete(spawn_pos_struct);
+	ClearPendingSelectableItemRewards(0, true);
+	ClearPendingItemRewards();
 }
 }
 
 
 EQ2Packet* Player::serialize(Player* player, int16 version){
 EQ2Packet* Player::serialize(Player* player, int16 version){
@@ -245,7 +248,7 @@ void PlayerInfo::CalculateXPPercentages(){
 	if(info_struct->xp_needed > 0){
 	if(info_struct->xp_needed > 0){
 		float percentage = ((double)info_struct->xp / info_struct->xp_needed) * 1000;
 		float percentage = ((double)info_struct->xp / info_struct->xp_needed) * 1000;
 		info_struct->xp_yellow = (int16)percentage;
 		info_struct->xp_yellow = (int16)percentage;
-		info_struct->xp_blue = (int16)(100-((ceil(percentage/100) - (percentage/100)) * 100));
+		info_struct->xp_blue = (int16)((percentage-info_struct->xp_yellow)*1000);
 		info_struct->xp_blue_vitality_bar = 0;
 		info_struct->xp_blue_vitality_bar = 0;
 		info_struct->xp_yellow_vitality_bar = 0;
 		info_struct->xp_yellow_vitality_bar = 0;
 		if(player->GetXPVitality() > 0){
 		if(player->GetXPVitality() > 0){
@@ -264,7 +267,7 @@ void PlayerInfo::CalculateTSXPPercentages(){
 	if(info_struct->ts_xp_needed > 0){
 	if(info_struct->ts_xp_needed > 0){
 		float percentage = ((double)info_struct->ts_xp / info_struct->ts_xp_needed) * 1000;
 		float percentage = ((double)info_struct->ts_xp / info_struct->ts_xp_needed) * 1000;
 		info_struct->tradeskill_exp_yellow = (int16)percentage;
 		info_struct->tradeskill_exp_yellow = (int16)percentage;
-		info_struct->tradeskill_exp_blue = (int16)(100-((ceil(percentage/100) - (percentage/100)) * 100));
+		info_struct->tradeskill_exp_blue = (int16)((percentage - info_struct->tradeskill_exp_yellow) * 1000);
 		/*info_struct->xp_blue_vitality_bar = 0;
 		/*info_struct->xp_blue_vitality_bar = 0;
 		info_struct->xp_yellow_vitality_bar = 0;
 		info_struct->xp_yellow_vitality_bar = 0;
 		if(player->GetXPVitality() > 0){
 		if(player->GetXPVitality() > 0){
@@ -978,20 +981,26 @@ EQ2Packet* PlayerInfo::serialize(int16 version, int16 modifyPos, int32 modifyVal
 		packet->setDataByName("decrease_falling_dmg", 169);
 		packet->setDataByName("decrease_falling_dmg", 169);
 
 
 
 
-		info_struct->xp_blue = 12;
-		info_struct->xp_yellow = 16;
-		info_struct->weight = 50;
 		info_struct->max_weight = 200;
 		info_struct->max_weight = 200;
 		//packet->setDataByName("auto_attack", 1);
 		//packet->setDataByName("auto_attack", 1);
 		//492
 		//492
-
-		packet->setDataByName("exp_yellow", info_struct->xp_yellow);
-		packet->setDataByName("exp_blue", info_struct->xp_blue);
-		packet->setDataByName("tradeskill_exp_yellow", info_struct->tradeskill_exp_yellow);
-		packet->setDataByName("tradeskill_exp_blue", info_struct->tradeskill_exp_blue);
-
-
-
+		if (version <= 546) {
+			packet->setDataByName("exp_yellow", info_struct->xp_yellow / 10);
+			packet->setDataByName("exp_blue", info_struct->xp_blue/10);
+		}
+		else {
+			packet->setDataByName("exp_yellow", info_struct->xp_yellow);
+			packet->setDataByName("exp_blue", info_struct->xp_blue);
+		}
+		
+		if (version <= 546) {
+			packet->setDataByName("tradeskill_exp_yellow", info_struct->tradeskill_exp_yellow / 10);
+			packet->setDataByName("tradeskill_exp_blue", info_struct->tradeskill_exp_blue / 10);
+		}
+		else {
+			packet->setDataByName("tradeskill_exp_yellow", info_struct->tradeskill_exp_yellow);
+			packet->setDataByName("tradeskill_exp_blue", info_struct->tradeskill_exp_blue);
+		}		
 
 
 		packet->setDataByName("attack", info_struct->cur_attack);
 		packet->setDataByName("attack", info_struct->cur_attack);
 		packet->setDataByName("attack_base", info_struct->attack_base);
 		packet->setDataByName("attack_base", info_struct->attack_base);
@@ -1000,9 +1009,6 @@ EQ2Packet* PlayerInfo::serialize(int16 version, int16 modifyPos, int32 modifyVal
 		packet->setDataByName("mitigation_skill2", info_struct->mitigation_skill2);
 		packet->setDataByName("mitigation_skill2", info_struct->mitigation_skill2);
 		packet->setDataByName("mitigation_skill3", info_struct->mitigation_skill3);
 		packet->setDataByName("mitigation_skill3", info_struct->mitigation_skill3);
 
 
-
-
-
 		packet->setDataByName("mitigation_max", info_struct->max_mitigation);
 		packet->setDataByName("mitigation_max", info_struct->max_mitigation);
 
 
 		packet->setDataByName("savagery", 250);
 		packet->setDataByName("savagery", 250);
@@ -1709,7 +1715,9 @@ vector<EQ2Packet*>	Player::UnequipItem(int16 index, sint32 bag_id, int8 slot, in
 
 
 			if (item->GetItemScript() && lua_interface)
 			if (item->GetItemScript() && lua_interface)
 				lua_interface->RunItemScript(item->GetItemScript(), "unequipped", item, this);
 				lua_interface->RunItemScript(item->GetItemScript(), "unequipped", item, this);
-
+			const char* zone_script = world.GetZoneScript(GetZone()->GetZoneID());
+			if (zone_script && lua_interface)
+				lua_interface->RunZoneScript(zone_script, "item_unequipped", GetZone(), this, item->details.item_id, item->name.c_str(), 0, item->details.unique_id);
 			item->save_needed = true;
 			item->save_needed = true;
 			EQ2Packet* outapp = item_list.serialize(this, version);
 			EQ2Packet* outapp = item_list.serialize(this, version);
 			if (outapp) {
 			if (outapp) {
@@ -1920,9 +1928,9 @@ bool Player::CanEquipItem(Item* item) {
 						if (item->CheckLevel(GetAdventureClass(), GetTradeskillClass(), GetLevel()))
 						if (item->CheckLevel(GetAdventureClass(), GetTradeskillClass(), GetLevel()))
 							return true;
 							return true;
 						else
 						else
-							client->Message(CHANNEL_COLOR_RED, "You must be at least level %u to equip \\aITEM %u 0:%s\\/a.", item->generic_info.adventure_default_level, item->details.item_id, item->name.c_str());
+							client->Message(CHANNEL_COLOR_RED, "You must be at least level %u to equip %s.", item->generic_info.adventure_default_level, item->CreateItemLink(client->GetVersion()).c_str());
 					else
 					else
-						client->Message(CHANNEL_COLOR_RED, "Your class may not equip \\aITEM %u 0:%s\\/a.", item->details.item_id, item->name.c_str());
+						client->Message(CHANNEL_COLOR_RED, "Your class may not equip %s.", item->CreateItemLink(client->GetVersion()).c_str());
 				}
 				}
 				else
 				else
 					client->SimpleMessage(0, "You lack the skill required to equip this item.");
 					client->SimpleMessage(0, "You lack the skill required to equip this item.");
@@ -1994,6 +2002,9 @@ vector<EQ2Packet*> Player::EquipItem(int16 index, int16 version, int8 slot_id) {
 			item->save_needed = true;
 			item->save_needed = true;
 			packets.push_back(item->serialize(version, false));
 			packets.push_back(item->serialize(version, false));
 			SetEquipment(item);
 			SetEquipment(item);
+			const char* zone_script = world.GetZoneScript(GetZone()->GetZoneID());
+			if (zone_script && lua_interface)
+				lua_interface->RunZoneScript(zone_script, "item_equipped", GetZone(), this, item->details.item_id, item->name.c_str(), 0, item->details.unique_id);
 			int32 bag_id = item->details.inv_slot_id;
 			int32 bag_id = item->details.inv_slot_id;
 			if (item->generic_info.condition == 0) {
 			if (item->generic_info.condition == 0) {
 				Client* client = GetZone()->GetClientBySpawn(this);
 				Client* client = GetZone()->GetClientBySpawn(this);
@@ -2001,7 +2012,7 @@ vector<EQ2Packet*> Player::EquipItem(int16 index, int16 version, int8 slot_id) {
 
 
 					LogWrite(MISC__TODO, 1, "TODO", "Send popup text in red 'Some of your equipment is broken!'\n\t(%s, function: %s, line #: %i)", __FILE__, __FUNCTION__, __LINE__);
 					LogWrite(MISC__TODO, 1, "TODO", "Send popup text in red 'Some of your equipment is broken!'\n\t(%s, function: %s, line #: %i)", __FILE__, __FUNCTION__, __LINE__);
 
 
-					client->Message(CHANNEL_COLOR_RED, "Your \\aITEM %u %u:%s\\/a is worn out and will not be effective until repaired.", item->details.item_id, item->details.unique_id, item->name.c_str());
+					client->Message(CHANNEL_COLOR_RED, "Your %s is worn out and will not be effective until repaired.", item->CreateItemLink(GetVersion(), true).c_str());
 				}
 				}
 			}
 			}
 			packets.push_back(equipment_list.serialize(version, this));
 			packets.push_back(equipment_list.serialize(version, this));
@@ -3753,6 +3764,7 @@ bool Player::AddXP(int32 xp_amount){
 	if(current_xp_percent >= miniding_min_percent){
 	if(current_xp_percent >= miniding_min_percent){
 		SetHP(GetTotalHP());
 		SetHP(GetTotalHP());
 		SetPower(GetTotalPower());
 		SetPower(GetTotalPower());
+		GetZone()->SendCastSpellPacket(332, this, this); //send mini level up spell effect
 	}
 	}
 	return true;
 	return true;
 }
 }
@@ -3980,7 +3992,7 @@ vector<Quest*>* Player::CheckQuestsSpellUpdate(Spell* spell) {
 	return quest_updates;
 	return quest_updates;
 }
 }
 
 
-PacketStruct* Player::GetQuestJournalPacket(bool all_quests, int16 version, int32 crc, int32 current_quest_id){
+PacketStruct* Player::GetQuestJournalPacket(bool all_quests, int16 version, int32 crc, int32 current_quest_id, bool updated){
 	PacketStruct* packet = configReader.getStruct("WS_QuestJournalUpdate", version);
 	PacketStruct* packet = configReader.getStruct("WS_QuestJournalUpdate", version);
 	Quest* quest = 0;
 	Quest* quest = 0;
 	if(packet){
 	if(packet){
@@ -4035,7 +4047,7 @@ PacketStruct* Player::GetQuestJournalPacket(bool all_quests, int16 version, int3
 				if(!all_quests && !itr->second->GetUpdateRequired())
 				if(!all_quests && !itr->second->GetUpdateRequired())
 					continue;
 					continue;
 				quest = itr->second;
 				quest = itr->second;
-				if(!quest->GetDeleted())
+				if(!quest->GetDeleted() && !quest->GetCompleted())
 					packet->setArrayDataByName("active", 1, i);
 					packet->setArrayDataByName("active", 1, i);
 				packet->setArrayDataByName("name", quest->GetName(), i);
 				packet->setArrayDataByName("name", quest->GetName(), i);
 				packet->setArrayDataByName("quest_type", quest->GetType(), i);
 				packet->setArrayDataByName("quest_type", quest->GetType(), i);
@@ -4047,9 +4059,10 @@ PacketStruct* Player::GetQuestJournalPacket(bool all_quests, int16 version, int3
 					packet->setArrayDataByName("turned_in", 1, i);
 					packet->setArrayDataByName("turned_in", 1, i);
 					packet->setArrayDataByName("completed", 1, i);
 					packet->setArrayDataByName("completed", 1, i);
 					packet->setArrayDataByName("visible", 1, i);
 					packet->setArrayDataByName("visible", 1, i);
-					display_status += QUEST_DISPLAY_STATUS_COMPLETED;
-					packet->setArrayDataByName("unknown3", 1, i);
+					display_status += QUEST_DISPLAY_STATUS_COMPLETED;					
 				}
 				}
+				if (updated)
+					packet->setArrayDataByName("quest_updated", 1, i);
 				packet->setArrayDataByName("quest_id", quest->GetQuestID(), i);
 				packet->setArrayDataByName("quest_id", quest->GetQuestID(), i);
 				packet->setArrayDataByName("day", quest->GetDay(), i);
 				packet->setArrayDataByName("day", quest->GetDay(), i);
 				packet->setArrayDataByName("month", quest->GetMonth(), i);
 				packet->setArrayDataByName("month", quest->GetMonth(), i);
@@ -4091,7 +4104,6 @@ PacketStruct* Player::GetQuestJournalPacket(bool all_quests, int16 version, int3
 				if (itr->second->IsRepeatable())
 				if (itr->second->IsRepeatable())
 					packet->setArrayDataByName("repeatable", 1, i);
 					packet->setArrayDataByName("repeatable", 1, i);
 				
 				
-				packet->setArrayDataByName("visible", 0, i);
 				packet->setArrayDataByName("display_status", display_status, i);
 				packet->setArrayDataByName("display_status", display_status, i);
 				i++;
 				i++;
 			}
 			}
@@ -4113,7 +4125,7 @@ PacketStruct* Player::GetQuestJournalPacket(bool all_quests, int16 version, int3
 	return packet;
 	return packet;
 }
 }
 
 
-PacketStruct* Player::GetQuestJournalPacket(Quest* quest, int16 version, int32 crc) {
+PacketStruct* Player::GetQuestJournalPacket(Quest* quest, int16 version, int32 crc, bool updated) {
 	if (!quest)
 	if (!quest)
 		return 0;
 		return 0;
 
 
@@ -4125,7 +4137,7 @@ PacketStruct* Player::GetQuestJournalPacket(Quest* quest, int16 version, int32 c
 		packet->setArrayDataByName("quest_zones_zone", quest->GetType());
 		packet->setArrayDataByName("quest_zones_zone", quest->GetType());
 		packet->setArrayDataByName("quest_zones_zone_id", 0);
 		packet->setArrayDataByName("quest_zones_zone_id", 0);
 		
 		
-		if(!quest->GetDeleted())
+		if(!quest->GetDeleted() && !quest->GetCompleted())
 			packet->setArrayDataByName("active", 1);
 			packet->setArrayDataByName("active", 1);
 
 
 		packet->setArrayDataByName("name", quest->GetName());
 		packet->setArrayDataByName("name", quest->GetName());
@@ -4138,17 +4150,14 @@ PacketStruct* Player::GetQuestJournalPacket(Quest* quest, int16 version, int32 c
 			packet->setArrayDataByName("completed", 1);
 			packet->setArrayDataByName("completed", 1);
 		if(quest->GetTurnedIn()) {
 		if(quest->GetTurnedIn()) {
 			packet->setArrayDataByName("turned_in", 1);
 			packet->setArrayDataByName("turned_in", 1);
-			packet->setArrayDataByName("completed", 1);
-			packet->setArrayDataByName("visible", 1);
+			packet->setArrayDataByName("completed", 1);			
 			display_status += QUEST_DISPLAY_STATUS_COMPLETED;
 			display_status += QUEST_DISPLAY_STATUS_COMPLETED;
-			packet->setArrayDataByName("unknown3", 1);
 		}
 		}
 		packet->setArrayDataByName("quest_id", quest->GetQuestID());
 		packet->setArrayDataByName("quest_id", quest->GetQuestID());
 		packet->setArrayDataByName("day", quest->GetDay());
 		packet->setArrayDataByName("day", quest->GetDay());
 		packet->setArrayDataByName("month", quest->GetMonth());
 		packet->setArrayDataByName("month", quest->GetMonth());
 		packet->setArrayDataByName("year", quest->GetYear());
 		packet->setArrayDataByName("year", quest->GetYear());
 		packet->setArrayDataByName("level", quest->GetQuestLevel());
 		packet->setArrayDataByName("level", quest->GetQuestLevel());
-
 		int8 difficulty = 0;
 		int8 difficulty = 0;
 		string category = quest->GetType();
 		string category = quest->GetType();
 		if(category == "Tradeskill")
 		if(category == "Tradeskill")
@@ -4187,10 +4196,9 @@ PacketStruct* Player::GetQuestJournalPacket(Quest* quest, int16 version, int32 c
 		if (quest->IsRepeatable())
 		if (quest->IsRepeatable())
 			packet->setArrayDataByName("repeatable", 1);
 			packet->setArrayDataByName("repeatable", 1);
 
 
-		packet->setArrayDataByName("visible", 0);
 		packet->setArrayDataByName("display_status", display_status);
 		packet->setArrayDataByName("display_status", display_status);
-		
-		packet->setDataByName("unknown3", 1);
+		if (updated)
+			packet->setDataByName("quest_updated", 1);
 		packet->setDataByName("visible_quest_id", quest->GetQuestID());
 		packet->setDataByName("visible_quest_id", quest->GetQuestID());
 		packet->setDataByName("player_crc", crc);
 		packet->setDataByName("player_crc", crc);
 		packet->setDataByName("player_name", GetName());
 		packet->setDataByName("player_name", GetName());

+ 74 - 3
EQ2/source/WorldServer/Player.h

@@ -388,7 +388,8 @@ public:
 	//int8	GetMaxArtLevel(){ return info->GetInfo()->max_art_level; }
 	//int8	GetMaxArtLevel(){ return info->GetInfo()->max_art_level; }
 	//int8	GetArtLevel(){ return info->GetInfo()->art_level; }
 	//int8	GetArtLevel(){ return info->GetInfo()->art_level; }
 
 
-
+	Client* GetClient() { return client; }
+	void SetClient(Client* client) { this->client = client; }
 	PlayerInfo* GetPlayerInfo();
 	PlayerInfo* GetPlayerInfo();
 	void SetCharSheetChanged(bool val);
 	void SetCharSheetChanged(bool val);
 	bool GetCharSheetChanged();
 	bool GetCharSheetChanged();
@@ -422,6 +423,12 @@ public:
 	float GetSideSpeed() {
 	float GetSideSpeed() {
 		return appearance.pos.SideSpeed;
 		return appearance.pos.SideSpeed;
 	}
 	}
+	int8 GetTutorialStep() {
+		return tutorial_step;
+	}
+	void SetTutorialStep(int8 val) {
+		tutorial_step = val;
+	}
 	void	AddMaintainedSpell(LuaSpell* spell);
 	void	AddMaintainedSpell(LuaSpell* spell);
 	void	AddSpellEffect(LuaSpell* spell);
 	void	AddSpellEffect(LuaSpell* spell);
 	void	RemoveMaintainedSpell(LuaSpell* spell);
 	void	RemoveMaintainedSpell(LuaSpell* spell);
@@ -568,6 +575,7 @@ public:
 	void	RemoveSpawn(Spawn* spawn);
 	void	RemoveSpawn(Spawn* spawn);
 	void	ClearRemovedSpawn(Spawn* spawn);
 	void	ClearRemovedSpawn(Spawn* spawn);
 	bool	ShouldSendSpawn(Spawn* spawn);
 	bool	ShouldSendSpawn(Spawn* spawn);
+	Client* client = 0;
 
 
 	Spawn* GetSpawnWithPlayerID(int32 id){
 	Spawn* GetSpawnWithPlayerID(int32 id){
 		Spawn* spawn = 0;
 		Spawn* spawn = 0;
@@ -637,7 +645,7 @@ public:
 		return new_index;
 		return new_index;
 	}
 	}
 
 
-	PacketStruct*	GetQuestJournalPacket(bool all_quests, int16 version, int32 crc, int32 current_quest_id);
+	PacketStruct*	GetQuestJournalPacket(bool all_quests, int16 version, int32 crc, int32 current_quest_id, bool updated = true);
 	void			RemoveQuest(int32 id, bool delete_quest);
 	void			RemoveQuest(int32 id, bool delete_quest);
 	vector<Quest*>* CheckQuestsChatUpdate(Spawn* spawn);
 	vector<Quest*>* CheckQuestsChatUpdate(Spawn* spawn);
 	vector<Quest*>* CheckQuestsItemUpdate(Item* item);
 	vector<Quest*>* CheckQuestsItemUpdate(Item* item);
@@ -654,6 +662,7 @@ public:
 	void AddHistoryRequiredSpawn(Spawn* spawn, int32 event_id);
 	void AddHistoryRequiredSpawn(Spawn* spawn, int32 event_id);
 	int16				spawn_index;
 	int16				spawn_index;
 	int32				spawn_id;
 	int32				spawn_id;
+	int8 tutorial_step;
 	map<int32, vector<int32>*>  player_spawn_quests_required;
 	map<int32, vector<int32>*>  player_spawn_quests_required;
 	map<int32, vector<int32>*>   player_spawn_history_required;
 	map<int32, vector<int32>*>   player_spawn_history_required;
 	Mutex				m_playerSpawnQuestsRequired;
 	Mutex				m_playerSpawnQuestsRequired;
@@ -739,6 +748,66 @@ public:
 	PlayerAchievementUpdateList * GetAchievementUpdateList() { return &achievement_update_list; }
 	PlayerAchievementUpdateList * GetAchievementUpdateList() { return &achievement_update_list; }
 	void				SetPendingCollectionReward(Collection *collection) { pending_collection_reward = collection; }
 	void				SetPendingCollectionReward(Collection *collection) { pending_collection_reward = collection; }
 	Collection *		GetPendingCollectionReward() { return pending_collection_reward; }
 	Collection *		GetPendingCollectionReward() { return pending_collection_reward; }
+	void AddPendingSelectableItemReward(int32 source_id, Item* item) {
+		if (pending_selectable_item_rewards.count(source_id) == 0)
+			pending_selectable_item_rewards[source_id] = vector<Item*>();
+		pending_selectable_item_rewards[source_id].push_back(item);
+	}
+	void AddPendingItemReward(Item* item) { 
+		pending_item_rewards.push_back(item);
+	}
+	bool HasPendingItemRewards() { return (pending_item_rewards.size() > 0 || pending_selectable_item_rewards.size() > 0); }
+	vector<Item*> GetPendingItemRewards() { return pending_item_rewards; }
+	map<int32, Item*> GetPendingSelectableItemReward(int32 item_id) { //since the client sends the selected item id, we need to have the associated source and remove all of them.  Yes, there is an edge case if multiple sources have the same Item in them, but limited on what the client sends (just a single item id)
+		map<int32, Item*> ret;
+		if (pending_selectable_item_rewards.size() > 0) {
+			map<int32, vector<Item*>>::iterator map_itr;
+			for (map_itr = pending_selectable_item_rewards.begin(); map_itr != pending_selectable_item_rewards.end(); map_itr++) {
+				vector<Item*>::iterator itr;
+				for (itr = map_itr->second.begin(); itr != map_itr->second.end(); itr++) {
+					if ((*itr)->details.item_id == item_id) {
+						ret[map_itr->first] = *itr;
+						break;
+					}
+				}
+				if (ret.size() > 0)
+					break;
+			}			
+		}
+		return map<int32, Item*>();
+	}
+	void ClearPendingSelectableItemRewards(int32 source_id, bool all = false) { 
+		if (pending_selectable_item_rewards.size() > 0) {
+			map<int32, vector<Item*>>::iterator map_itr;
+			if (all) {
+				for (map_itr = pending_selectable_item_rewards.begin(); map_itr != pending_selectable_item_rewards.end(); map_itr++) {
+					vector<Item*>::iterator itr;
+					for (itr = map_itr->second.begin(); itr != map_itr->second.end(); itr++) {
+						safe_delete(*itr);
+					}
+				}
+				pending_selectable_item_rewards.clear();
+			}
+			else {
+				if (pending_selectable_item_rewards.count(source_id) > 0) {
+					vector<Item*>::iterator itr;
+					for (itr = pending_selectable_item_rewards[source_id].begin(); itr != pending_selectable_item_rewards[source_id].end(); itr++) {
+						safe_delete(*itr);
+					}
+					pending_selectable_item_rewards.erase(source_id);
+				}
+			}			
+		}
+	}	
+	void ClearPendingItemRewards() { //the client doesn't send any reference to where the pending rewards came from, so if they collect one, we should just them all of them at once
+		if (pending_item_rewards.size() > 0) {
+			vector<Item*>::iterator itr;
+			for (itr = pending_item_rewards.begin(); itr != pending_item_rewards.end(); itr++) {
+				safe_delete(*itr);
+			}
+			pending_item_rewards.clear();
+		}
+	}
 	void RemoveSpellBookEntry(int32 spell_id, bool remove_passives_from_list = true);
 	void RemoveSpellBookEntry(int32 spell_id, bool remove_passives_from_list = true);
 	void ResortSpellBook(int32 sort_by, int32 order, int32 pattern, int32 maxlvl_only, int32 book_type);
 	void ResortSpellBook(int32 sort_by, int32 order, int32 pattern, int32 maxlvl_only, int32 book_type);
 
 
@@ -844,7 +913,7 @@ public:
 	///<summary>Get all the spells the player has with the given id</summary>
 	///<summary>Get all the spells the player has with the given id</summary>
 	vector<Spell*> GetSpellBookSpellsByTimer(int32 timerID);
 	vector<Spell*> GetSpellBookSpellsByTimer(int32 timerID);
 
 
-	PacketStruct* GetQuestJournalPacket(Quest* quest, int16 version, int32 crc);
+	PacketStruct* GetQuestJournalPacket(Quest* quest, int16 version, int32 crc, bool updated = true);
 
 
 	void SetSpawnInfoStruct(PacketStruct* packet) { safe_delete(spawn_info_struct); spawn_info_struct = packet; }
 	void SetSpawnInfoStruct(PacketStruct* packet) { safe_delete(spawn_info_struct); spawn_info_struct = packet; }
 	void SetSpawnVisStruct(PacketStruct* packet) { safe_delete(spawn_vis_struct); spawn_vis_struct = packet; }
 	void SetSpawnVisStruct(PacketStruct* packet) { safe_delete(spawn_vis_struct); spawn_vis_struct = packet; }
@@ -967,6 +1036,8 @@ private:
 	Guild*				guild;
 	Guild*				guild;
 	PlayerCollectionList collection_list;
 	PlayerCollectionList collection_list;
 	Collection *		pending_collection_reward;
 	Collection *		pending_collection_reward;
+	vector<Item*>		pending_item_rewards;
+	map<int32, vector<Item*>>		pending_selectable_item_rewards;
 	PlayerTitlesList	player_titles_list;
 	PlayerTitlesList	player_titles_list;
 	PlayerRecipeList	recipe_list;
 	PlayerRecipeList	recipe_list;
 	PlayerLanguagesList	player_languages_list;
 	PlayerLanguagesList	player_languages_list;

+ 1 - 1
EQ2/source/WorldServer/PlayerGroups.cpp

@@ -139,7 +139,7 @@ void PlayerGroup::SimpleGroupMessage(const char* message) {
 	for(itr = m_members.begin(); itr != m_members.end(); itr++) {
 	for(itr = m_members.begin(); itr != m_members.end(); itr++) {
 		GroupMemberInfo* info = *itr;
 		GroupMemberInfo* info = *itr;
 		if(info->client)
 		if(info->client)
-			info->client->SimpleMessage(CHANNEL_GROUP, message);
+			info->client->SimpleMessage(CHANNEL_GROUP_CHAT, message);
 	}
 	}
 	MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
 	MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
 }
 }

+ 10 - 4
EQ2/source/WorldServer/Quests.cpp

@@ -955,6 +955,7 @@ EQ2Packet* Quest::QuestJournalReply(int16 version, int32 player_crc, Player* pla
 		packet->setDataByName("month", month);
 		packet->setDataByName("month", month);
 		packet->setDataByName("year", year);
 		packet->setDataByName("year", year);
 		packet->setDataByName("level", level);
 		packet->setDataByName("level", level);
+		packet->setDataByName("visible", 1);		
 		/* To get the quest timer to work you need to set unknown, index 4 to 1 and the time stamp
 		/* To get the quest timer to work you need to set unknown, index 4 to 1 and the time stamp
 		to the current time + the time in seconds you want to show in the journal*/
 		to the current time + the time in seconds you want to show in the journal*/
 		if (m_timestamp > 0) {
 		if (m_timestamp > 0) {
@@ -1076,8 +1077,9 @@ EQ2Packet* Quest::QuestJournalReply(int16 version, int32 player_crc, Player* pla
 					packet->setSubArrayLengthByName("num_tasks", task_group[primary_order[i]->GetTaskGroup()].size(), index);
 					packet->setSubArrayLengthByName("num_tasks", task_group[primary_order[i]->GetTaskGroup()].size(), index);
 					packet->setSubArrayLengthByName("num_updates", task_group[primary_order[i]->GetTaskGroup()].size(), index);
 					packet->setSubArrayLengthByName("num_updates", task_group[primary_order[i]->GetTaskGroup()].size(), index);
 					map_data_count += task_group[primary_order[i]->GetTaskGroup()].size();
 					map_data_count += task_group[primary_order[i]->GetTaskGroup()].size();
-					if (task_group[primary_order[i]->GetTaskGroup()].size() > 0)
-						packet->setDataByName("bullets", 1);
+					if (task_group[primary_order[i]->GetTaskGroup()].size() > 0) {
+						packet->setDataByName("bullets", 1);						
+					}
 					for (int32 x = 0; x < task_group[primary_order[i]->GetTaskGroup()].size(); x++) {
 					for (int32 x = 0; x < task_group[primary_order[i]->GetTaskGroup()].size(); x++) {
 						step = task_group[primary_order[i]->GetTaskGroup()].at(x);
 						step = task_group[primary_order[i]->GetTaskGroup()].at(x);
 						if (!step)
 						if (!step)
@@ -1087,12 +1089,14 @@ EQ2Packet* Quest::QuestJournalReply(int16 version, int32 player_crc, Player* pla
 						packet->setSubArrayDataByName("task_completed", 1, index, x);
 						packet->setSubArrayDataByName("task_completed", 1, index, x);
 						packet->setSubArrayDataByName("index", x, index, x);
 						packet->setSubArrayDataByName("index", x, index, x);
 						packet->setSubArrayDataByName("update_currentval", step->GetQuestCurrentQuantity(), index, x);
 						packet->setSubArrayDataByName("update_currentval", step->GetQuestCurrentQuantity(), index, x);
+						if(step->GetQuestCurrentQuantity() > 0)
+							packet->setDataByName("journal_updated", 1);
 						packet->setSubArrayDataByName("update_maxval", step->GetQuestNeededQuantity(), index, x);
 						packet->setSubArrayDataByName("update_maxval", step->GetQuestNeededQuantity(), index, x);
 						if (step->GetUpdateTargetName())
 						if (step->GetUpdateTargetName())
 							packet->setSubArrayDataByName("update_target_name", step->GetUpdateTargetName(), index, x);
 							packet->setSubArrayDataByName("update_target_name", step->GetUpdateTargetName(), index, x);
 						packet->setSubArrayDataByName("icon", step->GetIcon(), index, x);
 						packet->setSubArrayDataByName("icon", step->GetIcon(), index, x);
 						if (updateStep && step == updateStep) {
 						if (updateStep && step == updateStep) {
-							packet->setDataByName("update", 1);
+							packet->setDataByName("update", 1);							
 							//	packet->setDataByName("unknown5d", 1);
 							//	packet->setDataByName("unknown5d", 1);
 							if (!quest_failure)
 							if (!quest_failure)
 								packet->setDataByName("onscreen_update", 1);
 								packet->setDataByName("onscreen_update", 1);
@@ -1154,6 +1158,8 @@ EQ2Packet* Quest::QuestJournalReply(int16 version, int32 player_crc, Player* pla
 							packet->setSubArrayDataByName("task_completed", 0, index, x);
 							packet->setSubArrayDataByName("task_completed", 0, index, x);
 						packet->setSubArrayDataByName("index", x, index, x);
 						packet->setSubArrayDataByName("index", x, index, x);
 						packet->setSubArrayDataByName("update_currentval", step->GetQuestCurrentQuantity(), index, x);
 						packet->setSubArrayDataByName("update_currentval", step->GetQuestCurrentQuantity(), index, x);
+						if (step->GetQuestCurrentQuantity() > 0)
+							packet->setDataByName("journal_updated", 1);
 						packet->setSubArrayDataByName("update_maxval", step->GetQuestNeededQuantity(), index, x);
 						packet->setSubArrayDataByName("update_maxval", step->GetQuestNeededQuantity(), index, x);
 						packet->setSubArrayDataByName("icon", step->GetIcon(), index, x);
 						packet->setSubArrayDataByName("icon", step->GetIcon(), index, x);
 						if (step->GetUpdateTargetName())
 						if (step->GetUpdateTargetName())
@@ -1180,7 +1186,7 @@ EQ2Packet* Quest::QuestJournalReply(int16 version, int32 player_crc, Player* pla
 				else {
 				else {
 					if (task_group_names.count(secondary_order[i]) > 0) {
 					if (task_group_names.count(secondary_order[i]) > 0) {
 						step = secondary_order[i];
 						step = secondary_order[i];
-						if (updateStep && step == updateStep) {
+						if (updateStep && step == updateStep) {							
 							packet->setDataByName("update", 1);
 							packet->setDataByName("update", 1);
 							if (!quest_failure)
 							if (!quest_failure)
 								packet->setDataByName("onscreen_update", 1);
 								packet->setDataByName("onscreen_update", 1);

+ 34 - 12
EQ2/source/WorldServer/Spawn.cpp

@@ -203,7 +203,11 @@ void Spawn::InitializeHeaderPacketData(Player* player, PacketStruct* header, int
 				header->setArrayDataByName("command_list_command", primary_command_list[i]->command.c_str(), i);
 				header->setArrayDataByName("command_list_command", primary_command_list[i]->command.c_str(), i);
 			}
 			}
 		}
 		}
-		header->setMediumStringByName("default_command", primary_command_list[0]->command.c_str());
+		if (header->GetVersion() <= 546) {
+			header->setMediumStringByName("default_command", primary_command_list[0]->name.c_str());
+		}
+		else
+			header->setMediumStringByName("default_command", primary_command_list[0]->command.c_str());
 		header->setDataByName("max_distance", primary_command_list[0]->distance);
 		header->setDataByName("max_distance", primary_command_list[0]->distance);
 	}
 	}
 	if (spawn_group_list && MSpawnGroup){
 	if (spawn_group_list && MSpawnGroup){
@@ -236,6 +240,8 @@ void Spawn::InitializeVisPacketData(Player* player, PacketStruct* vis_packet) {
 		vis_packet->setDataByName("targetable", appearance.targetable);
 		vis_packet->setDataByName("targetable", appearance.targetable);
 		vis_packet->setDataByName("show_name", appearance.display_name);
 		vis_packet->setDataByName("show_name", appearance.display_name);
 		vis_packet->setDataByName("attackable", appearance.attackable);
 		vis_packet->setDataByName("attackable", appearance.attackable);
+		if(appearance.attackable == 1)
+			vis_packet->setDataByName("attackable_icon", 1); 
 		if (IsPlayer()) {
 		if (IsPlayer()) {
 			if (((Player*)this)->IsGroupMember(player))
 			if (((Player*)this)->IsGroupMember(player))
 				vis_packet->setDataByName("group_member", 1);
 				vis_packet->setDataByName("group_member", 1);
@@ -255,7 +261,7 @@ void Spawn::InitializeVisPacketData(Player* player, PacketStruct* vis_packet) {
 
 
 			if (appearance.attackable == 1)
 			if (appearance.attackable == 1)
 				arrow_color = player->GetArrowColor(GetLevel());
 				arrow_color = player->GetArrowColor(GetLevel());
-			/*if (version <= 283) {
+			if (version <= 283) {
 				if (GetMerchantID() > 0)
 				if (GetMerchantID() > 0)
 					arrow_color += 7;
 					arrow_color += 7;
 				else {
 				else {
@@ -273,9 +279,12 @@ void Spawn::InitializeVisPacketData(Player* player, PacketStruct* vis_packet) {
 						}
 						}
 					}
 					}
 				}
 				}
-			}*/
+			}
 			vis_packet->setDataByName("arrow_color", arrow_color);
 			vis_packet->setDataByName("arrow_color", arrow_color);
-			vis_packet->setDataByName("locked_no_loot", appearance.locked_no_loot);
+			if (appearance.attackable == 0)
+				vis_packet->setDataByName("locked_no_loot", 1);
+			else
+				vis_packet->setDataByName("locked_no_loot", appearance.locked_no_loot);
 			if (player->GetArrowColor(GetLevel()) == ARROW_COLOR_GRAY)
 			if (player->GetArrowColor(GetLevel()) == ARROW_COLOR_GRAY)
 				if (npc_con == -4)
 				if (npc_con == -4)
 					npc_con = -3;
 					npc_con = -3;
@@ -340,6 +349,9 @@ void Spawn::InitializeVisPacketData(Player* player, PacketStruct* vis_packet) {
 		if ((req_quests_override & 256) > 0)
 		if ((req_quests_override & 256) > 0)
 			vis_packet->setDataByName("hand_flag", 1);
 			vis_packet->setDataByName("hand_flag", 1);
 	}
 	}
+	if (version == 546 && GetMerchantID() > 0) {
+		vis_packet->setDataByName("guild", "<Merchant>");
+	}
 }
 }
 
 
 void Spawn::InitializeFooterPacketData(Player* player, PacketStruct* footer) {
 void Spawn::InitializeFooterPacketData(Player* player, PacketStruct* footer) {
@@ -712,7 +724,7 @@ uchar* Spawn::spawn_vis_changes(Player* player, int16 version){
 		safe_delete(xor_vis_packet);
 		safe_delete(xor_vis_packet);
 		xor_vis_packet = player->SetTempVisPacketForXOR(size);
 		xor_vis_packet = player->SetTempVisPacketForXOR(size);
 	}
 	}
-	if(orig_packet){
+	if(orig_packet){		
 		memcpy(xor_vis_packet, (uchar*)data->c_str(), size);
 		memcpy(xor_vis_packet, (uchar*)data->c_str(), size);
 		Encode(xor_vis_packet, orig_packet, size);
 		Encode(xor_vis_packet, orig_packet, size);
 	}
 	}
@@ -1025,7 +1037,9 @@ uchar* Spawn::spawn_info_changes_ex(Player* player, int16 version) {
 
 
 	uchar* orig_packet = player->GetSpawnInfoPacketForXOR(id);
 	uchar* orig_packet = player->GetSpawnInfoPacketForXOR(id);
 
 
-	if (orig_packet) {
+	if (orig_packet) {		
+		//if (!IsPlayer() && this->EngagedInCombat())
+			//packet->PrintPacket();
 		memcpy(xor_info_packet, (uchar*)data->c_str(), size);
 		memcpy(xor_info_packet, (uchar*)data->c_str(), size);
 		Encode(xor_info_packet, orig_packet, size);
 		Encode(xor_info_packet, orig_packet, size);
 	}
 	}
@@ -1087,7 +1101,9 @@ uchar* Spawn::spawn_vis_changes_ex(Player* player, int16 version) {
 		xor_vis_packet = player->SetTempVisPacketForXOR(size);
 		xor_vis_packet = player->SetTempVisPacketForXOR(size);
 	}
 	}
 
 
-	if (orig_packet) {
+	if (orig_packet) {		
+		//if (!IsPlayer() && this->EngagedInCombat())
+		//	vis_struct->PrintPacket();
 		memcpy(xor_vis_packet, (uchar*)data->c_str(), size);
 		memcpy(xor_vis_packet, (uchar*)data->c_str(), size);
 		Encode(xor_vis_packet, orig_packet, size);
 		Encode(xor_vis_packet, orig_packet, size);
 	}
 	}
@@ -1151,6 +1167,8 @@ uchar* Spawn::spawn_pos_changes_ex(Player* player, int16 version) {
 	}
 	}
 
 
 	if (orig_packet) {
 	if (orig_packet) {
+		//if (!IsPlayer() && this->EngagedInCombat())
+		//	packet->PrintPacket();
 		memcpy(xor_pos_packet, (uchar*)data->c_str(), size);
 		memcpy(xor_pos_packet, (uchar*)data->c_str(), size);
 		Encode(xor_pos_packet, orig_packet, size);
 		Encode(xor_pos_packet, orig_packet, size);
 	}
 	}
@@ -2204,18 +2222,19 @@ void Spawn::InitializeInfoPacketData(Player* spawn, PacketStruct* packet) {
 		if (appearance.show_level == 0)
 		if (appearance.show_level == 0)
 			packet->setDataByName("hide_health", 1);
 			packet->setDataByName("hide_health", 1);
 	}
 	}
-	if (GetHP() <= 0 && IsEntity())
+	if (GetHP() <= 0 && IsEntity()) {
 		packet->setDataByName("corpse", 1);
 		packet->setDataByName("corpse", 1);
+		packet->setDataByName("loot_icon", 1); 
+	}
 	if (!IsPlayer())
 	if (!IsPlayer())
 		packet->setDataByName("npc", 1);
 		packet->setDataByName("npc", 1);
 	if (GetMerchantID() > 0)
 	if (GetMerchantID() > 0)
-		packet->setDataByName("merchant", 1);
-	if (EngagedInCombat())
-		packet->setDataByName("in_combat", 1);
-
+		packet->setDataByName("merchant", 1);		
+	packet->setDataByName("effective_level", (int8)GetLevel());
 	packet->setDataByName("level", (int8)GetLevel());
 	packet->setDataByName("level", (int8)GetLevel());
 	packet->setDataByName("unknown4", (int8)GetLevel());
 	packet->setDataByName("unknown4", (int8)GetLevel());
 	packet->setDataByName("difficulty", appearance.encounter_level); //6);
 	packet->setDataByName("difficulty", appearance.encounter_level); //6);
+	packet->setDataByName("unknown6", 1);
 	packet->setDataByName("heroic_flag", appearance.heroic_flag);
 	packet->setDataByName("heroic_flag", appearance.heroic_flag);
 	if (!IsObject() && !IsGroundSpawn() && !IsWidget() && !IsSign())
 	if (!IsObject() && !IsGroundSpawn() && !IsWidget() && !IsSign())
 		packet->setDataByName("interaction_flag", 12); //this makes NPCs head turn to look at you
 		packet->setDataByName("interaction_flag", 12); //this makes NPCs head turn to look at you
@@ -2513,6 +2532,9 @@ void Spawn::InitializeInfoPacketData(Player* spawn, PacketStruct* packet) {
 		else
 		else
 			packet->setDataByName("follow_target", 0xFFFFFFFF);
 			packet->setDataByName("follow_target", 0xFFFFFFFF);
 	}
 	}
+	else if (!IsPet()) {
+		packet->setDataByName("follow_target", 0xFFFFFFFF);
+	}
 	if (GetTarget() && GetTarget()->GetTargetable())
 	if (GetTarget() && GetTarget()->GetTargetable())
 		packet->setDataByName("target_id", ((spawn->GetIDWithPlayerSpawn(GetTarget()) * -1) - 1));
 		packet->setDataByName("target_id", ((spawn->GetIDWithPlayerSpawn(GetTarget()) * -1) - 1));
 	else
 	else

+ 4 - 4
EQ2/source/WorldServer/SpellProcess.cpp

@@ -395,7 +395,7 @@ bool SpellProcess::DeleteCasterSpell(LuaSpell* spell){
 						string fade_message = spell->spell->GetSpellData()->fade_message;
 						string fade_message = spell->spell->GetSpellData()->fade_message;
 						if(fade_message.find("%t") != string::npos)
 						if(fade_message.find("%t") != string::npos)
 							fade_message.replace(fade_message.find("%t"), 2, target->GetName());
 							fade_message.replace(fade_message.find("%t"), 2, target->GetName());
-						client->Message(CHANNEL_COLOR_SPELL_FADE, fade_message.c_str());
+						client->Message(CHANNEL_SPELLS_OTHER, fade_message.c_str());
 					}
 					}
 				}
 				}
 			}
 			}
@@ -1388,7 +1388,7 @@ bool SpellProcess::CastProcessedSpell(LuaSpell* spell, bool passive){
 					string success_message = spell->spell->GetSpellData()->success_message;
 					string success_message = spell->spell->GetSpellData()->success_message;
 					if(success_message.find("%t") != string::npos)
 					if(success_message.find("%t") != string::npos)
 						success_message.replace(success_message.find("%t"), 2, spell->caster->GetName());
 						success_message.replace(success_message.find("%t"), 2, spell->caster->GetName());
-					client->Message(CHANNEL_COLOR_SPELL, success_message.c_str());
+					client->Message(CHANNEL_SPELLS, success_message.c_str());
 				}
 				}
 			}
 			}
 			if(spell->spell->GetSpellData()->effect_message.length() > 0){
 			if(spell->spell->GetSpellData()->effect_message.length() > 0){
@@ -1397,7 +1397,7 @@ bool SpellProcess::CastProcessedSpell(LuaSpell* spell, bool passive){
 					effect_message.replace(effect_message.find("%t"), 2, target->GetName());
 					effect_message.replace(effect_message.find("%t"), 2, target->GetName());
 				if (effect_message.find("%c") != string::npos)
 				if (effect_message.find("%c") != string::npos)
 					effect_message.replace(effect_message.find("%c"), 2, spell->caster->GetName());
 					effect_message.replace(effect_message.find("%c"), 2, spell->caster->GetName());
-				spell->caster->GetZone()->SimpleMessage(CHANNEL_COLOR_SPELL_EFFECT, effect_message.c_str(), target, 50);
+				spell->caster->GetZone()->SimpleMessage(CHANNEL_SPELLS_OTHER, effect_message.c_str(), target, 50);
 			}
 			}
 			target->GetZone()->CallSpawnScript(target, SPAWN_SCRIPT_CASTED_ON, spell->caster, spell->spell->GetName());
 			target->GetZone()->CallSpawnScript(target, SPAWN_SCRIPT_CASTED_ON, spell->caster, spell->spell->GetName());
 		}
 		}
@@ -1613,7 +1613,7 @@ void SpellProcess::Interrupted(Entity* caster, Spawn* interruptor, int16 error_c
 			if(interruptor && interruptor->IsPlayer())
 			if(interruptor && interruptor->IsPlayer())
 			{
 			{
 				client = interruptor->GetZone()->GetClientBySpawn(interruptor);
 				client = interruptor->GetZone()->GetClientBySpawn(interruptor);
-				client->Message(CHANNEL_COLOR_SPELL_INTERRUPT, "You interrupt %s's ability to cast!", interruptor->GetName());
+				client->Message(CHANNEL_SPELLS_OTHER, "You interrupt %s's ability to cast!", interruptor->GetName());
 			}
 			}
 			
 			
 		}
 		}

+ 3 - 3
EQ2/source/WorldServer/Tradeskills/Tradeskills.cpp

@@ -368,7 +368,7 @@ void TradeskillMgr::StopCrafting(Client* client, bool lock) {
 	else {
 	else {
 		item->details.count = qty;
 		item->details.count = qty;
 		// use CHANNEL_COLOR_CHAT_RELATIONSHIP as that is the same value (4) as it is in a log for this message
 		// use CHANNEL_COLOR_CHAT_RELATIONSHIP as that is the same value (4) as it is in a log for this message
-		client->Message(CHANNEL_COLOR_CHAT_RELATIONSHIP, "You created \\aITEM %u 0:%s\\/a.", item->details.item_id, item->name.c_str());
+		client->Message(CHANNEL_COLOR_CHAT_RELATIONSHIP, "You created %s.", item->CreateItemLink(client->GetVersion()).c_str());
 		client->AddItem(item);
 		client->AddItem(item);
 		//Check for crafting quest updates
 		//Check for crafting quest updates
 		int8 update_amt = 0;
 		int8 update_amt = 0;
@@ -383,7 +383,7 @@ void TradeskillMgr::StopCrafting(Client* client, bool lock) {
 	if (xp > 0) {
 	if (xp > 0) {
 		int16 level = client->GetPlayer()->GetTSLevel();
 		int16 level = client->GetPlayer()->GetTSLevel();
 		if (client->GetPlayer()->AddTSXP((int32)xp)) {
 		if (client->GetPlayer()->AddTSXP((int32)xp)) {
-			client->Message(CHANNEL_COLOR_EXP, "You gain %u Tradeskill XP!", (int32)xp);
+			client->Message(CHANNEL_REWARD, "You gain %u Tradeskill XP!", (int32)xp);
 			LogWrite(PLAYER__DEBUG, 0, "Player", "Player: %s earned %u tradeskill experience.", client->GetPlayer()->GetName(), (int32)xp);
 			LogWrite(PLAYER__DEBUG, 0, "Player", "Player: %s earned %u tradeskill experience.", client->GetPlayer()->GetName(), (int32)xp);
 			if(client->GetPlayer()->GetTSLevel() != level)
 			if(client->GetPlayer()->GetTSLevel() != level)
 				client->ChangeTSLevel(level, client->GetPlayer()->GetTSLevel());
 				client->ChangeTSLevel(level, client->GetPlayer()->GetTSLevel());
@@ -431,7 +431,7 @@ void TradeskillMgr::CheckTradeskillEvent(Client* client, int16 icon) {
 	tradeskillList[client]->eventCountered = countered;
 	tradeskillList[client]->eventCountered = countered;
 
 
 	// send the success or fail message to the client
 	// send the success or fail message to the client
-	client->Message(CHANNEL_COLOR_WHITE, "You %s %s.", countered ? "successfully countered" : "failed to counter", tradeskillList[client]->CurrentEvent->Name);
+	client->Message(CHANNEL_NARRATIVE, "You %s %s.", countered ? "successfully countered" : "failed to counter", tradeskillList[client]->CurrentEvent->Name);
 	
 	
 	// unlock the list and send the result packet
 	// unlock the list and send the result packet
 	m_tradeskills.releasewritelock(__FUNCTION__, __LINE__);
 	m_tradeskills.releasewritelock(__FUNCTION__, __LINE__);

+ 3 - 3
EQ2/source/WorldServer/Transmute.cpp

@@ -221,7 +221,7 @@ void Transmute::CompleteTransmutation(Client* client, Player* player) {
 		if (item2) item2 = new Item(item2);
 		if (item2) item2 = new Item(item2);
 	}
 	}
 
 
-	client->Message(89, "You transmute %s and create: ", item->CreateItemLink(false).c_str());
+	client->Message(89, "You transmute %s and create: ", item->CreateItemLink(GetVersion(), false).c_str());
 
 
 	player->item_list.RemoveItem(item, true);
 	player->item_list.RemoveItem(item, true);
 
 
@@ -232,7 +232,7 @@ void Transmute::CompleteTransmutation(Client* client, Player* player) {
 
 
 	if (item1) {
 	if (item1) {
 		item1->details.count = 1;
 		item1->details.count = 1;
-		client->Message(89, "     %s", item1->CreateItemLink(false).c_str());
+		client->Message(89, "     %s", item1->CreateItemLink(GetVersion(), false).c_str());
 		client->AddItem(item1);
 		client->AddItem(item1);
 
 
 		if (packet) {
 		if (packet) {
@@ -248,7 +248,7 @@ void Transmute::CompleteTransmutation(Client* client, Player* player) {
 
 
 	if (item2) {
 	if (item2) {
 		item2->details.count = 1;
 		item2->details.count = 1;
-		client->Message(89, "     %s", item2->CreateItemLink(false).c_str());
+		client->Message(89, "     %s", item2->CreateItemLink(GetVersion(), false).c_str());
 		client->AddItem(item2);
 		client->AddItem(item2);
 
 
 		if (packet) {
 		if (packet) {

+ 6 - 41
EQ2/source/WorldServer/World.cpp

@@ -409,7 +409,7 @@ bool ZoneList::HandleGlobalChatMessage(Client* from, char* to, int16 channel, co
 		return false;
 		return false;
 	}
 	}
 
 
-	if(channel == CHANNEL_TELL){
+	if(channel == CHANNEL_PRIVATE_TELL){
 		Client* find_client = zone_list.GetClientByCharName(to);
 		Client* find_client = zone_list.GetClientByCharName(to);
 		if(!find_client || find_client->GetPlayer()->IsIgnored(from->GetPlayer()->GetName()))
 		if(!find_client || find_client->GetPlayer()->IsIgnored(from->GetPlayer()->GetName()))
 			return false;
 			return false;
@@ -419,50 +419,15 @@ bool ZoneList::HandleGlobalChatMessage(Client* from, char* to, int16 channel, co
 		}
 		}
 		else
 		else
 		{
 		{
-			PacketStruct* packet = configReader.getStruct("WS_HearChat", from->GetVersion());
-			if(packet){
-				packet->setMediumStringByName("from", from->GetPlayer()->GetName());
-				packet->setMediumStringByName("to", find_client->GetPlayer()->GetName());
-				packet->setDataByName("channel", CHANNEL_TELL);
-				packet->setDataByName("from_spawn_id", 0xFFFFFFFF);
-				packet->setDataByName("to_spawn_id", 0xFFFFFFFF);
-				packet->setDataByName("unknown2", 1, 1);
-				packet->setDataByName("show_bubble", 1);
-				packet->setDataByName("understood", 1);
-				packet->setDataByName("time", 2); 
-				packet->setMediumStringByName("message", message);
-				if(channel_name)
-					packet->setMediumStringByName("channel_name", channel_name);
-				EQ2Packet* outpacket = packet->serialize();
-				//DumpPacket(outpacket);
-				find_client->QueuePacket(outpacket->Copy());
-				from->QueuePacket(outpacket);
-				safe_delete(packet);
-			}
+			find_client->HandleTellMessage(from, message);
+			from->HandleTellMessage(from, message);			
 			if (find_client->GetPlayer()->get_character_flag(CF_AFK)) {
 			if (find_client->GetPlayer()->get_character_flag(CF_AFK)) {
-				PacketStruct* packet2 = configReader.getStruct("WS_HearChat", from->GetVersion());
-				if (packet2) {
-					packet2->setMediumStringByName("from", find_client->GetPlayer()->GetName());
-					packet2->setMediumStringByName("to", from->GetPlayer()->GetName());
-					packet2->setDataByName("channel", CHANNEL_TELL);
-					packet2->setDataByName("from_spawn_id", 0xFFFFFFFF);
-					packet2->setDataByName("to_spawn_id", 0xFFFFFFFF);
-					packet2->setDataByName("unknown2", 1, 1);
-					packet2->setDataByName("show_bubble", 1);
-					packet2->setDataByName("understood", 1);
-					packet2->setDataByName("time", 2);
-					packet2->setMediumStringByName("message", find_client->GetPlayer()->GetAwayMessage().c_str());
-					if (channel_name)
-						packet2->setMediumStringByName("channel_name", channel_name);
-					EQ2Packet* outpacket = packet2->serialize();
-					from->QueuePacket(outpacket->Copy());
-					find_client->QueuePacket(outpacket);
-					safe_delete(packet2);
-				}
+				find_client->HandleTellMessage(find_client, find_client->GetPlayer()->GetAwayMessage().c_str());
+				from->HandleTellMessage(find_client, find_client->GetPlayer()->GetAwayMessage().c_str());
 			}
 			}
 		}
 		}
 	}
 	}
-	else if(channel == CHANNEL_GROUP) {
+	else if(channel == CHANNEL_GROUP_SAY) {
 		GroupMemberInfo* gmi = from->GetPlayer()->GetGroupMemberInfo();
 		GroupMemberInfo* gmi = from->GetPlayer()->GetGroupMemberInfo();
 		if(gmi)
 		if(gmi)
 			world.GetGroupManager()->GroupMessage(gmi->group_id, message);
 			world.GetGroupManager()->GroupMessage(gmi->group_id, message);

+ 1 - 1
EQ2/source/WorldServer/WorldDatabase.cpp

@@ -4039,7 +4039,7 @@ void WorldDatabase::LoadPlayerMail(Client* client, bool new_only) {
 			result = query.RunQuery2(Q_SELECT, "SELECT `id`, `player_to_id`, `player_from`, `subject`, `mail_body`, `already_read`, `mail_type`, `coin_copper`, `coin_silver`, `coin_gold`, `coin_plat`, `stack`, `postage_cost`, `attachment_cost`, `char_item_id`, `time_sent`, `expire_time` FROM `character_mail` WHERE `player_to_id`=%u", client->GetCharacterID());
 			result = query.RunQuery2(Q_SELECT, "SELECT `id`, `player_to_id`, `player_from`, `subject`, `mail_body`, `already_read`, `mail_type`, `coin_copper`, `coin_silver`, `coin_gold`, `coin_plat`, `stack`, `postage_cost`, `attachment_cost`, `char_item_id`, `time_sent`, `expire_time` FROM `character_mail` WHERE `player_to_id`=%u", client->GetCharacterID());
 		if (result && mysql_num_rows(result) > 0) {
 		if (result && mysql_num_rows(result) > 0) {
 			MYSQL_ROW row;
 			MYSQL_ROW row;
-			client->SimpleMessage(CHANNEL_COLOR_MAIL, "You've got mail! :)");
+			client->SimpleMessage(CHANNEL_NARRATIVE, "You've got mail! :)");
 			while (result && (row = mysql_fetch_row(result))) {
 			while (result && (row = mysql_fetch_row(result))) {
 				Mail* mail = new Mail;
 				Mail* mail = new Mail;
 				mail->mail_id = atoul(row[0]);
 				mail->mail_id = atoul(row[0]);

File diff suppressed because it is too large
+ 434 - 118
EQ2/source/WorldServer/client.cpp


+ 8 - 4
EQ2/source/WorldServer/client.h

@@ -151,6 +151,8 @@ public:
 	void	SetReadyForSpawns(bool val);
 	void	SetReadyForSpawns(bool val);
 	void	QueuePacket(EQ2Packet* app, bool attemptedCombine=false);
 	void	QueuePacket(EQ2Packet* app, bool attemptedCombine=false);
 	void	SendLoginInfo();
 	void	SendLoginInfo();
+	int8	GetMessageChannelColor(int8 channel_type);
+	void	HandleTellMessage(Client* from, const char* message);
 	void	SimpleMessage(int8 color, const char* message);
 	void	SimpleMessage(int8 color, const char* message);
 	void	Message(int8 type, const char* message, ...);
 	void	Message(int8 type, const char* message, ...);
 	void	SendSpellUpdate(Spell* spell);
 	void	SendSpellUpdate(Spell* spell);
@@ -242,7 +244,7 @@ public:
 	bool	UpdateQuickbarNeeded();
 	bool	UpdateQuickbarNeeded();
 	void	Save();
 	void	Save();
 	bool	remove_from_list;
 	bool	remove_from_list;
-	void	CloseLoot();
+	void	CloseLoot(int32 spawn_id);
 	void	SendPendingLoot(int32 total_coins, Spawn* entity);
 	void	SendPendingLoot(int32 total_coins, Spawn* entity);
 	void	Loot(int32 total_coins, vector<Item*>* items, Spawn* entity);
 	void	Loot(int32 total_coins, vector<Item*>* items, Spawn* entity);
 	void	Loot(Spawn* entity, bool attemptDisarm=true);
 	void	Loot(Spawn* entity, bool attemptDisarm=true);
@@ -253,18 +255,19 @@ public:
 	void	CheckPlayerQuestsItemUpdate(Item* item);
 	void	CheckPlayerQuestsItemUpdate(Item* item);
 	void	CheckPlayerQuestsSpellUpdate(Spell* spell);
 	void	CheckPlayerQuestsSpellUpdate(Spell* spell);
 	void	CheckPlayerQuestsLocationUpdate();
 	void	CheckPlayerQuestsLocationUpdate();
-	void	AddPendingQuest(Quest* quest);
+	void	AddPendingQuest(Quest* quest, bool forced = false);
 	void	AcceptQuest(int32 id);
 	void	AcceptQuest(int32 id);
 	Quest*	GetPendingQuest(int32 id);
 	Quest*	GetPendingQuest(int32 id);
 	void	RemovePendingQuest(Quest* quest);
 	void	RemovePendingQuest(Quest* quest);
 	void	SetPlayerQuest(Quest* quest, map<int32, int32>* progress);
 	void	SetPlayerQuest(Quest* quest, map<int32, int32>* progress);
 	void	AddPlayerQuest(Quest* quest, bool call_accepted = true, bool send_packets = true);
 	void	AddPlayerQuest(Quest* quest, bool call_accepted = true, bool send_packets = true);
 	void	RemovePlayerQuest(int32 id, bool send_update = true, bool delete_quest = true);
 	void	RemovePlayerQuest(int32 id, bool send_update = true, bool delete_quest = true);
-	void	SendQuestJournal(bool all_quests = false, Client* client = 0);
+	void	SendQuestJournal(bool all_quests = false, Client* client = 0, bool updated = true);
 	void	SendQuestUpdate(Quest* quest);
 	void	SendQuestUpdate(Quest* quest);
 	void	SendQuestFailure(Quest* quest);
 	void	SendQuestFailure(Quest* quest);
 	void	SendQuestUpdateStep(Quest* quest, int32 step, bool display_quest_helper = true);
 	void	SendQuestUpdateStep(Quest* quest, int32 step, bool display_quest_helper = true);
 	void	SendQuestUpdateStepImmediately(Quest* quest, int32 step, bool display_quest_helper = true);
 	void	SendQuestUpdateStepImmediately(Quest* quest, int32 step, bool display_quest_helper = true);
+	void	DisplayQuestRewards(Quest* quest, int64 coin, vector<Item*>* rewards=0, vector<Item*>* selectable_rewards=0, map<int32, sint32>* factions=0, const char* header="Quest Reward!", int32 status_points=0, const char* text=0);
 	void	DisplayQuestComplete(Quest* quest);
 	void	DisplayQuestComplete(Quest* quest);
 	void	DisplayRandomizeFeatures(int32 features);
 	void	DisplayRandomizeFeatures(int32 features);
 	void	AcceptQuestReward(Quest* quest, int32 item_id);
 	void	AcceptQuestReward(Quest* quest, int32 item_id);
@@ -329,6 +332,7 @@ public:
 	void	SearchStore(int32 page);
 	void	SearchStore(int32 page);
 	void	SetPlayer(Player* new_player){
 	void	SetPlayer(Player* new_player){
 		player = new_player;
 		player = new_player;
+		player->SetClient(this);
 	}
 	}
 	void	AddPendingQuestReward(Quest* quest);
 	void	AddPendingQuestReward(Quest* quest);
 	void	AddPendingQuestUpdate(int32 quest_id, int32 step_id, int32 progress = 0xFFFFFFFF);
 	void	AddPendingQuestUpdate(int32 quest_id, int32 step_id, int32 progress = 0xFFFFFFFF);
@@ -379,7 +383,7 @@ public:
 
 
 	bool GetInitialSpawnsSent() { return initial_spawns_sent; }
 	bool GetInitialSpawnsSent() { return initial_spawns_sent; }
 
 
-	void SendQuestJournalUpdate(Quest* quest);
+	void SendQuestJournalUpdate(Quest* quest, bool updated=true);
 
 
 	void AddQuestTimer(int32 quest_id);
 	void AddQuestTimer(int32 quest_id);
 
 

+ 42 - 54
EQ2/source/WorldServer/zoneserver.cpp

@@ -1892,7 +1892,7 @@ void ZoneServer::ProcessDrowning(){
 		for(itr = dead_list.begin(); itr != dead_list.end(); itr++){
 		for(itr = dead_list.begin(); itr != dead_list.end(); itr++){
 			RemoveDrowningVictim((*itr)->GetPlayer());
 			RemoveDrowningVictim((*itr)->GetPlayer());
 			KillSpawn(false, (*itr)->GetPlayer(), 0);
 			KillSpawn(false, (*itr)->GetPlayer(), 0);
-			(*itr)->SimpleMessage(CHANNEL_COLOR_WHITE, "You are sleeping with the fishes!  Glug, glug...");
+			(*itr)->SimpleMessage(CHANNEL_NARRATIVE, "You are sleeping with the fishes!  Glug, glug...");
 		}
 		}
 	}
 	}
 }
 }
@@ -3174,43 +3174,15 @@ void ZoneServer::SimpleMessage(int8 type, const char* message, Spawn* from, floa
 	MClientList.releasereadlock(__FUNCTION__, __LINE__);
 	MClientList.releasereadlock(__FUNCTION__, __LINE__);
 }
 }
 
 
-void ZoneServer::HandleChatMessage(Client* client, Spawn* from, const char* to, int16 channel, const char* message, float distance, const char* channel_name, bool show_bubble, int32 language) {
+void ZoneServer::HandleChatMessage(Client* client, Spawn* from, const char* to, int16 channel, const char* message, float distance, const char* channel_name, bool show_bubble, int32 language) {	
 	if ((!distance || from->GetDistance(client->GetPlayer()) <= distance) && (!from || !client->GetPlayer()->IsIgnored(from->GetName()))) {
 	if ((!distance || from->GetDistance(client->GetPlayer()) <= distance) && (!from || !client->GetPlayer()->IsIgnored(from->GetName()))) {
-		if (client->GetVersion() <= 283) {
-			switch (channel) {
-				case CHANNEL_GROUP: {
-					channel = CLASSIC_CLIENT_CHANNEL_GROUP;
-					break;
-				}
-				case CHANNEL_RAID: {
-					channel = CLASSIC_CLIENT_CHANNEL_RAID;
-					break;
-				}
-				case CHANNEL_GUILD: {
-					channel = CLASSIC_CLIENT_CHANNEL_GUILD;
-					break;
-				}
-				case CHANNEL_SAYTARGET: {
-					channel = CLASSIC_CLIENT_CHANNEL_SAYTARGET;
-					break;
-				}
-				case CHANNEL_TELL: {
-					channel = CLASSIC_CLIENT_CHANNEL_TELL;
-					break;
-				}
-				case CHANNEL_OOC: {
-					channel = CLASSIC_CLIENT_CHANNEL_OOC;
-					break;
-				}
-			}
-		}
 		PacketStruct* packet = configReader.getStruct("WS_HearChat", client->GetVersion());
 		PacketStruct* packet = configReader.getStruct("WS_HearChat", client->GetVersion());
 		if (packet) {
 		if (packet) {
 			if (from)
 			if (from)
 				packet->setMediumStringByName("from", from->GetName());
 				packet->setMediumStringByName("from", from->GetName());
 			if (client->GetPlayer() != from)
 			if (client->GetPlayer() != from)
 				packet->setMediumStringByName("to", client->GetPlayer()->GetName());
 				packet->setMediumStringByName("to", client->GetPlayer()->GetName());
-			packet->setDataByName("channel", channel);
+			packet->setDataByName("channel", client->GetMessageChannelColor(channel));
 			if (from && ((from == client->GetPlayer()) || (client->GetPlayer()->WasSentSpawn(from->GetID()) && !client->GetPlayer()->WasSpawnRemoved(from))))
 			if (from && ((from == client->GetPlayer()) || (client->GetPlayer()->WasSentSpawn(from->GetID()) && !client->GetPlayer()->WasSpawnRemoved(from))))
 				packet->setDataByName("from_spawn_id", client->GetPlayer()->GetIDWithPlayerSpawn(from));
 				packet->setDataByName("from_spawn_id", client->GetPlayer()->GetIDWithPlayerSpawn(from));
 			else
 			else
@@ -3988,7 +3960,7 @@ Spawn* ZoneServer::GetClosestSpawn(Spawn* spawn, int32 spawn_id){
 	MSpawnList.readlock(__FUNCTION__, __LINE__);
 	MSpawnList.readlock(__FUNCTION__, __LINE__);
 	for (itr = spawn_list.begin(); itr != spawn_list.end(); itr++) {
 	for (itr = spawn_list.begin(); itr != spawn_list.end(); itr++) {
 		test_spawn = itr->second;
 		test_spawn = itr->second;
-		if(test_spawn && test_spawn->GetDatabaseID() == spawn_id){
+		if(test_spawn && test_spawn != spawn && test_spawn->GetDatabaseID() == spawn_id){
 			test_distance = test_spawn->GetDistance(spawn);
 			test_distance = test_spawn->GetDistance(spawn);
 			if(test_distance < closest_distance){
 			if(test_distance < closest_distance){
 				closest_distance = test_distance;
 				closest_distance = test_distance;
@@ -4141,7 +4113,7 @@ void ZoneServer::SendCalculatedXP(Player* player, Spawn* victim){
 						if (xp > 0) {
 						if (xp > 0) {
 							int16 level = group_member->GetLevel();
 							int16 level = group_member->GetLevel();
 							if (group_member->AddXP((int32)xp)) {
 							if (group_member->AddXP((int32)xp)) {
-								gmi->client->Message(CHANNEL_COLOR_EXP, "You gain %u experience!", (int32)xp);
+								gmi->client->Message(CHANNEL_REWARD, "You gain %u experience!", (int32)xp);
 								LogWrite(PLAYER__DEBUG, 0, "Player", "Player: %s earned %u experience (GroupID %u)", group_member->GetName(), (int32)xp, player->GetGroupMemberInfo()->group_id);
 								LogWrite(PLAYER__DEBUG, 0, "Player", "Player: %s earned %u experience (GroupID %u)", group_member->GetName(), (int32)xp, player->GetGroupMemberInfo()->group_id);
 								if (group_member->GetLevel() != level)
 								if (group_member->GetLevel() != level)
 									gmi->client->ChangeLevel(level, group_member->GetLevel());
 									gmi->client->ChangeLevel(level, group_member->GetLevel());
@@ -4163,7 +4135,7 @@ void ZoneServer::SendCalculatedXP(Player* player, Spawn* victim){
 					return;
 					return;
 				int16 level = player->GetLevel();
 				int16 level = player->GetLevel();
 				if (player->AddXP((int32)xp)) {
 				if (player->AddXP((int32)xp)) {
-					client->Message(CHANNEL_COLOR_EXP, "You gain %u XP!", (int32)xp);
+					client->Message(CHANNEL_REWARD, "You gain %u XP!", (int32)xp);
 					LogWrite(PLAYER__DEBUG, 0, "Player", "Player: %s earned %u experience.", player->GetName(), (int32)xp);
 					LogWrite(PLAYER__DEBUG, 0, "Player", "Player: %s earned %u experience.", player->GetName(), (int32)xp);
 					if(player->GetLevel() != level)
 					if(player->GetLevel() != level)
 						client->ChangeLevel(level, player->GetLevel());
 						client->ChangeLevel(level, player->GetLevel());
@@ -4189,9 +4161,9 @@ void ZoneServer::ProcessFaction(Spawn* spawn, Client* client)
 			faction = master_faction_list.GetFaction(spawn->GetFactionID());
 			faction = master_faction_list.GetFaction(spawn->GetFactionID());
 
 
 			if(faction && update_result)
 			if(faction && update_result)
-				client->Message(CHANNEL_COLOR_FACTION, "Your faction standing with %s got worse.", faction->name.c_str());
+				client->Message(CHANNEL_FACTION, "Your faction standing with %s got worse.", faction->name.c_str());
 			else if(faction)
 			else if(faction)
-				client->Message(CHANNEL_COLOR_FACTION, "Your faction standing with %s could not possibly get any worse.", faction->name.c_str());
+				client->Message(CHANNEL_FACTION, "Your faction standing with %s could not possibly get any worse.", faction->name.c_str());
 
 
 			factions = master_faction_list.GetHostileFactions(spawn->GetFactionID());
 			factions = master_faction_list.GetHostileFactions(spawn->GetFactionID());
 
 
@@ -4207,9 +4179,9 @@ void ZoneServer::ProcessFaction(Spawn* spawn, Client* client)
 						faction = master_faction_list.GetFaction(*itr);
 						faction = master_faction_list.GetFaction(*itr);
 
 
 						if(faction && update_result)
 						if(faction && update_result)
-							client->Message(CHANNEL_COLOR_FACTION, "Your faction standing with %s got better.", faction->name.c_str());
+							client->Message(CHANNEL_FACTION, "Your faction standing with %s got better.", faction->name.c_str());
 						else if(faction)
 						else if(faction)
-							client->Message(CHANNEL_COLOR_FACTION, "Your faction standing with %s could not possibly get any better.", faction->name.c_str());
+							client->Message(CHANNEL_FACTION, "Your faction standing with %s could not possibly get any better.", faction->name.c_str());
 					}
 					}
 				}
 				}
 			}
 			}
@@ -4229,9 +4201,9 @@ void ZoneServer::ProcessFaction(Spawn* spawn, Client* client)
 					faction = master_faction_list.GetFaction(*itr);
 					faction = master_faction_list.GetFaction(*itr);
 
 
 					if(faction && update_result)
 					if(faction && update_result)
-						client->Message(CHANNEL_COLOR_FACTION, "Your faction standing with %s got worse.", faction->name.c_str());
+						client->Message(CHANNEL_FACTION, "Your faction standing with %s got worse.", faction->name.c_str());
 					else if(faction)
 					else if(faction)
-						client->Message(CHANNEL_COLOR_FACTION, "Your faction standing with %s could not possibly get any worse.", faction->name.c_str());
+						client->Message(CHANNEL_FACTION, "Your faction standing with %s could not possibly get any worse.", faction->name.c_str());
 				}
 				}
 			}
 			}
 		}
 		}
@@ -4374,7 +4346,7 @@ void ZoneServer::KillSpawn(bool spawnListLocked, Spawn* dead, Spawn* killer, boo
 						if (xp > 0) {
 						if (xp > 0) {
 							int16 level = spawn->GetLevel();
 							int16 level = spawn->GetLevel();
 							if (((Player*)spawn)->AddXP((int32)xp)) {
 							if (((Player*)spawn)->AddXP((int32)xp)) {
-								client->Message(CHANNEL_COLOR_EXP, "You gain %u XP!", (int32)xp);
+								client->Message(CHANNEL_REWARD, "You gain %u XP!", (int32)xp);
 								LogWrite(PLAYER__DEBUG, 0, "Player", "Player: %s earned %u experience.", spawn->GetName(), (int32)xp);
 								LogWrite(PLAYER__DEBUG, 0, "Player", "Player: %s earned %u experience.", spawn->GetName(), (int32)xp);
 								if (spawn->GetLevel() != level)
 								if (spawn->GetLevel() != level)
 									client->ChangeLevel(level, spawn->GetLevel());
 									client->ChangeLevel(level, spawn->GetLevel());
@@ -4449,6 +4421,9 @@ void ZoneServer::KillSpawn(bool spawnListLocked, Spawn* dead, Spawn* killer, boo
 
 
 		// Call the spawn scripts death() function
 		// Call the spawn scripts death() function
 		CallSpawnScript(dead, SPAWN_SCRIPT_DEATH, killer);
 		CallSpawnScript(dead, SPAWN_SCRIPT_DEATH, killer);
+		const char* zone_script = world.GetZoneScript(this->GetZoneID());
+		if (zone_script && lua_interface)
+			lua_interface->RunZoneScript(zone_script, "spawn_killed", this, dead, 0, 0, killer);
 	}
 	}
 	
 	
 	int32 victim_id = dead->GetID();
 	int32 victim_id = dead->GetID();
@@ -4797,7 +4772,7 @@ void ZoneServer::SendCastSpellPacket(LuaSpell* spell, Entity* caster){
 	safe_delete(packet);
 	safe_delete(packet);
 }
 }
 
 
-void ZoneServer::SendCastSpellPacket(int32 spell_visual, Spawn* target) {
+void ZoneServer::SendCastSpellPacket(int32 spell_visual, Spawn* target, Spawn* caster) {
 	if (target) {
 	if (target) {
 		vector<Client*>::iterator client_itr;
 		vector<Client*>::iterator client_itr;
 
 
@@ -4808,15 +4783,22 @@ void ZoneServer::SendCastSpellPacket(int32 spell_visual, Spawn* target) {
 				continue;
 				continue;
 			PacketStruct* packet = configReader.getStruct("WS_HearCastSpell", client->GetVersion());
 			PacketStruct* packet = configReader.getStruct("WS_HearCastSpell", client->GetVersion());
 			if (packet) {
 			if (packet) {
-				packet->setDataByName("spawn_id", 0xFFFFFFFF);
+				if (!caster) {
+					packet->setDataByName("spawn_id", 0xFFFFFFFF);
+					packet->setDataByName("invoker_id", 0xFFFFFFFF);
+				}
+				else {
+					int32 caster_id = client->GetPlayer()->GetIDWithPlayerSpawn(caster);
+					packet->setDataByName("spawn_id", caster_id);
+					packet->setDataByName("invoker_id", caster_id);
+				}
 				packet->setArrayLengthByName("num_targets", 1);
 				packet->setArrayLengthByName("num_targets", 1);
 				packet->setArrayDataByName("target", client->GetPlayer()->GetIDWithPlayerSpawn(target));
 				packet->setArrayDataByName("target", client->GetPlayer()->GetIDWithPlayerSpawn(target));
-				packet->setDataByName("spell_id", 0xFFFFFFFF);
 				packet->setDataByName("spell_visual", spell_visual);
 				packet->setDataByName("spell_visual", spell_visual);
 				packet->setDataByName("cast_time", 0);
 				packet->setDataByName("cast_time", 0);
 				packet->setDataByName("spell_id", 0);
 				packet->setDataByName("spell_id", 0);
 				packet->setDataByName("spell_level", 0);
 				packet->setDataByName("spell_level", 0);
-				packet->setDataByName("spell_tier", 0);
+				packet->setDataByName("spell_tier", 1);
 				client->QueuePacket(packet->serialize());
 				client->QueuePacket(packet->serialize());
 				safe_delete(packet);
 				safe_delete(packet);
 			}
 			}
@@ -5623,6 +5605,12 @@ void ZoneServer::ProcessSpell(Spell* spell, Entity* caster, Spawn* target, bool
 }
 }
 
 
 void ZoneServer::ProcessEntityCommand(EntityCommand* entity_command, Entity* caster, Spawn* target, bool lock) {
 void ZoneServer::ProcessEntityCommand(EntityCommand* entity_command, Entity* caster, Spawn* target, bool lock) {
+	if (target && target->GetSpawnScript()) {
+		Player* player = 0;
+		if (caster && caster->IsPlayer())
+			player = (Player*)caster;
+		CallSpawnScript(target, SPAWN_SCRIPT_CUSTOM, player, entity_command->command.c_str());
+	}
 	if (spellProcess)
 	if (spellProcess)
 		spellProcess->ProcessEntityCommand(this, entity_command, caster, target, lock);
 		spellProcess->ProcessEntityCommand(this, entity_command, caster, target, lock);
 }
 }
@@ -5885,9 +5873,9 @@ void ZoneServer::FindSpawn(Client* client, char* regSearchStr)
 		client->SimpleMessage(CHANNEL_COLOR_RED, "Try/Catch ZoneServer::FindSpawn(Client*, char* regSearchStr) failure.");
 		client->SimpleMessage(CHANNEL_COLOR_RED, "Try/Catch ZoneServer::FindSpawn(Client*, char* regSearchStr) failure.");
 		return;
 		return;
 	}
 	}
-	client->Message(CHANNEL_COLOR_WHITE, "RegEx Search Spawn List: %s", regSearchStr);
-	client->Message(CHANNEL_COLOR_WHITE, "Database ID | Spawn Name | X , Y , Z");
-	client->Message(CHANNEL_COLOR_WHITE, "========================");
+	client->Message(CHANNEL_NARRATIVE, "RegEx Search Spawn List: %s", regSearchStr);
+	client->Message(CHANNEL_NARRATIVE, "Database ID | Spawn Name | X , Y , Z");
+	client->Message(CHANNEL_NARRATIVE, "========================");
 	map<int32, Spawn*>::iterator itr;
 	map<int32, Spawn*>::iterator itr;
 	MSpawnList.readlock(__FUNCTION__, __LINE__);
 	MSpawnList.readlock(__FUNCTION__, __LINE__);
 	int32 spawnsFound = 0;
 	int32 spawnsFound = 0;
@@ -5907,12 +5895,12 @@ void ZoneServer::FindSpawn(Client* client, char* regSearchStr)
 
 
 		if (output)
 		if (output)
 		{
 		{
-			client->Message(CHANNEL_COLOR_WHITE, "%i | %s | %f , %f , %f", spawn->GetDatabaseID(), spawn->GetName(), spawn->GetX(), spawn->GetY(), spawn->GetZ());
+			client->Message(CHANNEL_NARRATIVE, "%i | %s | %f , %f , %f", spawn->GetDatabaseID(), spawn->GetName(), spawn->GetX(), spawn->GetY(), spawn->GetZ());
 			spawnsFound++;
 			spawnsFound++;
 		}
 		}
 	}
 	}
-	client->Message(CHANNEL_COLOR_WHITE, "========================", spawnsFound);
-	client->Message(CHANNEL_COLOR_WHITE, "%u Results Found.", spawnsFound);
+	client->Message(CHANNEL_NARRATIVE, "========================", spawnsFound);
+	client->Message(CHANNEL_NARRATIVE, "%u Results Found.", spawnsFound);
 	MSpawnList.releasereadlock(__FUNCTION__, __LINE__);
 	MSpawnList.releasereadlock(__FUNCTION__, __LINE__);
 }
 }
 
 
@@ -6169,11 +6157,11 @@ void ZoneServer::SetRain(float val) {
 		client->GetPlayer()->SetCharSheetChanged(true);
 		client->GetPlayer()->SetCharSheetChanged(true);
 		if( val >= 0.75 && !weather_signaled )
 		if( val >= 0.75 && !weather_signaled )
 		{
 		{
-			client->SimpleMessage(CHANNEL_COLOR_WHITE, "It starts to rain.");
+			client->SimpleMessage(CHANNEL_NARRATIVE, "It starts to rain.");
 		}
 		}
 		else if( val < 0.75 && weather_signaled ) 
 		else if( val < 0.75 && weather_signaled ) 
 		{
 		{
-			client->SimpleMessage(CHANNEL_COLOR_WHITE, "It stops raining.");
+			client->SimpleMessage(CHANNEL_NARRATIVE, "It stops raining.");
 		}
 		}
 	}
 	}
 	MClientList.releasereadlock(__FUNCTION__, __LINE__);
 	MClientList.releasereadlock(__FUNCTION__, __LINE__);
@@ -6526,7 +6514,7 @@ void ZoneServer::ResurrectSpawn(Spawn* spawn, Client* client) {
 			}
 			}
 
 
 			safe_delete(packet);
 			safe_delete(packet);
-			client->SimpleMessage(CHANNEL_COLOR_REVIVE, "You regain consciousness!");
+			client->SimpleMessage(CHANNEL_NARRATIVE, "You regain consciousness!");
 		}
 		}
 	}
 	}
 	spawn->SendSpawnChanges(true);
 	spawn->SendSpawnChanges(true);

+ 1 - 1
EQ2/source/WorldServer/zoneserver.h

@@ -311,7 +311,7 @@ public:
 	void    SendHealPacket(Spawn* caster, Spawn* target, int16 type, int32 heal_amt, const char* spell_name);
 	void    SendHealPacket(Spawn* caster, Spawn* target, int16 type, int32 heal_amt, const char* spell_name);
 	
 	
 	void	SendCastSpellPacket(LuaSpell* spell, Entity* caster);
 	void	SendCastSpellPacket(LuaSpell* spell, Entity* caster);
-	void	SendCastSpellPacket(int32 spell_visual, Spawn* target);
+	void	SendCastSpellPacket(int32 spell_visual, Spawn* target, Spawn* caster = 0);
 	void	SendCastEntityCommandPacket(EntityCommand* entity_command, int32 spawn_id, int32 target_id);
 	void	SendCastEntityCommandPacket(EntityCommand* entity_command, int32 spawn_id, int32 target_id);
 	void	TriggerCharSheetTimer();
 	void	TriggerCharSheetTimer();
 	
 	

+ 1 - 1
EQ2/source/common/ConfigReader.cpp

@@ -78,7 +78,7 @@ PacketStruct* ConfigReader::getStruct(const char* name, int16 version){
 				latest_version = *iter;
 				latest_version = *iter;
 		}		
 		}		
 		if (latest_version) {
 		if (latest_version) {
-			if (latest_version->GetOpcode() != OP_Unknown && latest_version->GetOpcodeValue(version) == 0xFFFF) {
+			if (latest_version->GetOpcode() != OP_Unknown && (latest_version->GetOpcodeValue(version) == 0xFFFF || latest_version->GetOpcodeValue(version)==0xCDCD)) {
 				LogWrite(PACKET__ERROR, 0, "Packet", "Could not find valid opcode for Packet Struct '%s' and client version %d", latest_version->GetName(), version);
 				LogWrite(PACKET__ERROR, 0, "Packet", "Could not find valid opcode for Packet Struct '%s' and client version %d", latest_version->GetName(), version);
 			}
 			}
 			else if(strlen(latest_version->GetOpcodeType()) == 0 || latest_version->GetOpcode() != OP_Unknown)
 			else if(strlen(latest_version->GetOpcodeType()) == 0 || latest_version->GetOpcode() != OP_Unknown)

+ 17 - 9
EQ2/source/common/PacketStruct.cpp

@@ -1565,28 +1565,36 @@ int32 PacketStruct::GetArraySizeByName(const char* name, int32 index) {
 int16 PacketStruct::GetOpcodeValue(int16 client_version) {
 int16 PacketStruct::GetOpcodeValue(int16 client_version) {
 	int16 opcode = 0xFFFF;
 	int16 opcode = 0xFFFF;
 	bool client_cmd = false;
 	bool client_cmd = false;
+	int16 OpcodeVersion = 0;
 #ifndef LOGIN
 #ifndef LOGIN
 	if (GetOpcode() == OP_ClientCmdMsg && strlen(GetOpcodeType()) > 0 && !IsSubPacket())
 	if (GetOpcode() == OP_ClientCmdMsg && strlen(GetOpcodeType()) > 0 && !IsSubPacket())
 		client_cmd = true;
 		client_cmd = true;
 #endif
 #endif
 	if (client_cmd) {
 	if (client_cmd) {
 		EmuOpcode sub_opcode = EQOpcodeManager[0]->NameSearch(GetOpcodeType());
 		EmuOpcode sub_opcode = EQOpcodeManager[0]->NameSearch(GetOpcodeType());
-		int16 opcode_val = 0;
 		if (sub_opcode != OP_Unknown) { //numbers should be used at OpcodeTypes, define them!
 		if (sub_opcode != OP_Unknown) { //numbers should be used at OpcodeTypes, define them!
-			int16 OpcodeVersion = GetOpcodeVersion(client_version);
-			if(EQOpcodeManager.count(OpcodeVersion) > 0)
+			OpcodeVersion = GetOpcodeVersion(client_version);
+			if (EQOpcodeManager.count(OpcodeVersion) > 0) {
 				opcode = EQOpcodeManager[OpcodeVersion]->EmuToEQ(sub_opcode);
 				opcode = EQOpcodeManager[OpcodeVersion]->EmuToEQ(sub_opcode);
+				if (opcode == 0xCDCD) {
+					LogWrite(PACKET__ERROR, 0, "Packet", "Could not find valid opcode for opcode: %s and client_version: %i", EQOpcodeManager[OpcodeVersion]->EmuToName(sub_opcode), client_version);
+				}
+			}
 		}		
 		}		
 	}
 	}
 	else {
 	else {
-		int16 OpcodeVersion = GetOpcodeVersion(client_version);
-		if (EQOpcodeManager.count(OpcodeVersion) > 0)
+		OpcodeVersion = GetOpcodeVersion(client_version);
+		if (EQOpcodeManager.count(OpcodeVersion) > 0) {
 			opcode = EQOpcodeManager[OpcodeVersion]->EmuToEQ(GetOpcode());
 			opcode = EQOpcodeManager[OpcodeVersion]->EmuToEQ(GetOpcode());
+			if (opcode == 0xCDCD) {
+				LogWrite(PACKET__ERROR, 0, "Packet", "Could not find valid opcode for opcode: %s and client_version: %i", EQOpcodeManager[OpcodeVersion]->EmuToName(GetOpcode()), client_version);
+			}
+		}
 	}
 	}
 #ifndef LOGIN
 #ifndef LOGIN
 	if(opcode == 0)
 	if(opcode == 0)
 		opcode = 0xFFFF;
 		opcode = 0xFFFF;
-#endif
+#endif	
 	return opcode;
 	return opcode;
 }
 }
 
 
@@ -1754,7 +1762,7 @@ void PacketStruct::serializePacket(bool clear) {
 	}
 	}
 #ifndef LOGIN
 #ifndef LOGIN
 	if (client_cmd) {
 	if (client_cmd) {
-		int16 opcode_val = GetOpcodeValue(client_version);		
+		int16 opcode_val = GetOpcodeValue(client_version);			
 		Clear();
 		Clear();
 		int32 size = client_data.length() + 3; //gotta add the opcode and oversized
 		int32 size = client_data.length() + 3; //gotta add the opcode and oversized
 		int8 oversized = 0xFF;
 		int8 oversized = 0xFF;
@@ -2541,8 +2549,8 @@ void PacketStruct::setItem(DataStruct* ds, Item* item, Player* player, int32 ind
 		//DumpPacket((uchar*)generic_string_data->c_str() + (9 + offset), size);
 		//DumpPacket((uchar*)generic_string_data->c_str() + (9 + offset), size);
 		//without these it will prompt for your character name
 		//without these it will prompt for your character name
 		if (offset == 0 || offset == -1 || offset == 2) {
 		if (offset == 0 || offset == -1 || offset == 2) {
-			if (client_version <= 546 && item->stack_count > 0)
-				out_data[0] = item->stack_count;
+			if (client_version <= 546 && item->details.count > 0)
+				out_data[0] = item->details.count;
 			else
 			else
 				out_data[0] = 1;
 				out_data[0] = 1;
 		}
 		}

+ 2 - 1
EQ2/win/EQ2WorldVC10.sln

@@ -16,7 +16,8 @@ Global
 		Release|x64 = Release|x64
 		Release|x64 = Release|x64
 	EndGlobalSection
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{FC063D75-089D-4470-B255-032A80DE3CCE}.Debug|Win32.ActiveCfg = Release|x64
+		{FC063D75-089D-4470-B255-032A80DE3CCE}.Debug|Win32.ActiveCfg = Debug|x64
+		{FC063D75-089D-4470-B255-032A80DE3CCE}.Debug|Win32.Build.0 = Debug|x64
 		{FC063D75-089D-4470-B255-032A80DE3CCE}.Debug|x64.ActiveCfg = Debug|x64
 		{FC063D75-089D-4470-B255-032A80DE3CCE}.Debug|x64.ActiveCfg = Debug|x64
 		{FC063D75-089D-4470-B255-032A80DE3CCE}.Debug|x64.Build.0 = Debug|x64
 		{FC063D75-089D-4470-B255-032A80DE3CCE}.Debug|x64.Build.0 = Debug|x64
 		{FC063D75-089D-4470-B255-032A80DE3CCE}.EQ2Login|Win32.ActiveCfg = Debug|x64
 		{FC063D75-089D-4470-B255-032A80DE3CCE}.EQ2Login|Win32.ActiveCfg = Debug|x64

+ 3 - 2
EQ2/win/VC10Projects/EQ2World.vcxproj

@@ -44,7 +44,7 @@
   <PropertyGroup Label="UserMacros" />
   <PropertyGroup Label="UserMacros" />
   <PropertyGroup>
   <PropertyGroup>
     <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
     <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)worldserver\</OutDir>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">E:\EQ2EMu\my_server\</OutDir>
     <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\$(ProjectName)__Debug_$(Platform)\</IntDir>
     <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\$(ProjectName)__Debug_$(Platform)\</IntDir>
     <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkIncremental>
     <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkIncremental>
     <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\..\..\bin\</OutDir>
     <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\..\..\bin\</OutDir>
@@ -76,7 +76,7 @@
     </Midl>
     </Midl>
     <ClCompile>
     <ClCompile>
       <Optimization>Disabled</Optimization>
       <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WORLD;_DEBUG;_EQDEBUG;WIN32;_CONSOLE;EQ2;EQN_DEBUG;_CRT_SECURE_NO_DEPRECATE;GLM_ENABLE_EXPERIMENTAL;GLM_FORCE_CTOR_INIT;GLM_FORCE_RADIANS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WRITE_PACKETS;WORLD;_DEBUG;_EQDEBUG;WIN32;_CONSOLE;EQ2;EQN_DEBUG;_CRT_SECURE_NO_DEPRECATE;GLM_ENABLE_EXPERIMENTAL;GLM_FORCE_CTOR_INIT;GLM_FORCE_RADIANS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExceptionHandling>Sync</ExceptionHandling>
       <ExceptionHandling>Sync</ExceptionHandling>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@@ -99,6 +99,7 @@
       <PrecompiledHeaderFile>
       <PrecompiledHeaderFile>
       </PrecompiledHeaderFile>
       </PrecompiledHeaderFile>
       <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
     </ClCompile>
     </ClCompile>
     <ResourceCompile>
     <ResourceCompile>
       <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+ 25 - 28
server/Quests/PeatBog/Reinforcements.lua

@@ -1,42 +1,39 @@
 --[[
 --[[
-	Script Name		:	Reinforcements.lua
-	Script Purpose	:	Handles the quest, "Reinforcements"
-	Script Author	:	Shatou
-	Script Date		:	1/8/2020
-	Script Notes	:	
-
-	Zone			:	Caves
-	Quest Giver		:	Lieutenant Dawson
-	Preceded by		:	A Final Foe
-	Followed by		:	A Lack of Information (in the Caves)
+	Script Name	: Quests/PeatBog/reinforcements.lua
+	Script Purpose	: Handles the quest, "Reinforcements"
+	Script Author	: Scatman
+	Script Date	: 2009.05.11
+	
+	Zone       : The Peat Bog
+	Quest Giver: Lieutenant Dawson
+	Preceded by: A Final Foe (a_final_foe.lua)
+	Followed by: None
 --]]
 --]]
 
 
-local CONSUL_BREE_ID = 1970004
 
 
 function Init(Quest)
 function Init(Quest)
-	AddQuestStepChat(Quest, 1, "I must report to Consul Bree in The Caves.", 1, "I must report to Consul Bree in The Caves to help in the defense of Qeynos.", 11, CONSUL_BREE_ID)
-	AddQuestStepCompleteAction(Quest, 1, "QuestComplete")
-end
 
 
-function QuestComplete(Quest, QuestGiver, Player)
-	-- The following UpdateQuestStepDescription and UpdateTaskGroupDescription are not needed, parser adds them for completion in case stuff needs to be moved around
-	UpdateQuestStepDescription(Quest, 1, "I have spoken with Consul Bree.")
-	UpdateQuestTaskGroupDescription(Quest, 1, "I have spoken with Consul Bree.")
 
 
-	UpdateQuestDescription(Quest, "I have spoken with Consul Bree.")
-	GiveQuestReward(Quest, Player)
-end
+	AddQuestStepChat(Quest, 1, "I must report to Consul Bree in The Caves.", 1, "I must report to Consul Bree in The Caves to help in the defense of Qeynos.", 0, 1970010)
+	AddQuestStepCompleteAction(Quest, 1, "QuestComplete")
 
 
-function Reload(Quest, QuestGiver, Player, Step)
-	if Step == 1 then
-		QuestComplete(Quest, QuestGiver, Player)
-	end
 end
 end
 
 
 function Accepted(Quest, QuestGiver, Player)
 function Accepted(Quest, QuestGiver, Player)
-	-- Add dialog here for when the quest is accepted
+	FaceTarget(QuestGiver, Player)
+	conversation = CreateConversation()
+	
+	AddConversationOption(conversation, "I can do this.")
+	StartConversation(conversation, QuestGiver, Player, "I know you can. Qeynos is counting on you, " .. GetName(Player) .. ". Make us proud!")
 end
 end
 
 
 function Declined(Quest, QuestGiver, Player)
 function Declined(Quest, QuestGiver, Player)
-	-- Add dialog here for when the quest is declined
-end
+end
+
+function QuestComplete(Quest, QuestGiver, Player)
+	UpdateQuestDescription(Quest, "I have spoken with Consul Bree.")
+	GiveQuestReward(Quest, Player)
+end
+
+function Reload(Quest, QuestGiver, Player, Step)
+end

+ 50 - 63
server/Quests/PeatBog/ambushed.lua

@@ -1,93 +1,80 @@
 --[[
 --[[
-	Script Name	: Quests/PeatBog/ambushed.lua
-	Script Purpose	: Handles the quest, "Ambushed"
-	Script Author	: Scatman
-	Script Date	: 2009.05.10
-	
-	Zone       : The Peat Bog
-	Quest Giver: Lieutenant Dawson
-	Preceded by: Mysterious Machine (mysterious_machine.lua)
-	Followed by: On the Move (on_the_move.lua)
+	Script Name		:	Ambushed.lua
+	Script Purpose	:	Handles the quest, "Ambushed"
+	Script Author	:	Shatou
+	Script Date		:	1/8/2020
+	Script Notes	:	
+
+	Zone			:	Peat Bog
+	Quest Giver		:	Lieutenant Dawson
+	Preceded by		:	Mysterious Machine
+	Followed by		:	On The Move
 --]]
 --]]
 
 
+local LIEUTENANT_DAWSON_ID = 1980012
+local ENTITY_COMMAND_INSPECT = 61
+local AMBUSHED_QUEST_ID = 509
 
 
 function Init(Quest)
 function Init(Quest)
-
-
-	AddQuestStep(Quest, 1, "I need to investigate the ambush site west of Two Logs Pond, which is south of the sewer grate.", 1, 100, "Lieutenant Dawson has asked me to investigate three ambush sites.", 0)
-	AddQuestStep(Quest, 2, "I need to investigate the ambush site in the north eastern corner of the area east of Two Logs Pond.", 1, 100, "Lieutenant Dawson has asked me to investigate three ambush sites.", 0)
-	AddQuestStep(Quest, 3, "I need to investigate the ambush site in the south end of the area east of Two Logs Pond.", 1, 100, "Lieutenant Dawson has asked me to investigate three ambush sites.", 0)
-	AddQuestStepCompleteAction(Quest, 1, "Step1_Complete_Site1")
-	AddQuestStepCompleteAction(Quest, 2, "Step2_Complete_Site2")
-	AddQuestStepCompleteAction(Quest, 3, "Step3_Complete_Site3")
-
-end
-
-function Accepted(Quest, QuestGiver, Player)
-	FaceTarget(QuestGiver, Player)
-	conversation = CreateConversation()
+	AddQuestStepSpell(Quest, 1, "I need to investigate the ambush site west of Two Logs Pond, which is south of the sewer grate.", 1, 100, "Lieutenant Dawson has asked me to investigate three ambush sites.", 11, ENTITY_COMMAND_INSPECT)
+	AddQuestStepCompleteAction(Quest, 1, "Step1Complete")
+	
+	AddQuestStepSpell(Quest, 2, "I need to investigate the ambush site in the north eastern corner of the area east of Two Logs Pond.", 1, 100, "Lieutenant Dawson has asked me to investigate three ambush sites.", 11, ENTITY_COMMAND_INSPECT)
+	AddQuestStepCompleteAction(Quest, 2, "Step2Complete")
 	
 	
-	PlayFlavor(QuestGiver, "voiceover/english/tutorial_revamp/lieutenant_dawson/qey_adv04_bog/quests/dawson/dawson011a.mp3", "", "", 3239354610, 1196418998, Player)
-	AddConversationOption(conversation, "You're welcome, and thank you.")
-	StartConversation(conversation, QuestGiver, Player, "Thank you for your help, be safe.")
+	AddQuestStepSpell(Quest, 3, "I need to investigate the ambush site in the south end of the area east of Two Logs Pond.", 1, 100, "Lieutenant Dawson has asked me to investigate three ambush sites.", 11, ENTITY_COMMAND_INSPECT)
+	AddQuestStepCompleteAction(Quest, 3, "Step3Complete")
 end
 end
 
 
-function Declined(Quest, QuestGiver, Player)
+function CheckProgress(Quest, QuestGiver, Player)
+	if QuestStepIsComplete(Player, AMBUSHED_QUEST_ID, 1) and QuestStepIsComplete(Player, AMBUSHED_QUEST_ID, 2) and QuestStepIsComplete(Player, AMBUSHED_QUEST_ID, 3) then
+		UpdateQuestTaskGroupDescription(Quest, 1, "I have investigated all three ambush sites.")
+		
+		AddQuestStepChat(Quest, 4, "I need to return to Lieutenant Dawson.", 1, "I need to tell Lieutenant Dawson of what I found at one of the ambush sites.", 11, ENTITY_COMMAND_INSPECT)
+		AddQuestStepCompleteAction(Quest, 4, "QuestComplete")
+	end
 end
 end
 
 
-function Step1_Complete_Site1(Quest, QuestGiver, Player)
+function Step1Complete(Quest, QuestGiver, Player)
 	UpdateQuestStepDescription(Quest, 1, "I have investigated the ambush site near Two Logs Pond.")
 	UpdateQuestStepDescription(Quest, 1, "I have investigated the ambush site near Two Logs Pond.")
-
-	if QuestIsComplete(Player, 217) then
-		Multiple_Steps_Complete(Quest, QuestGiver, Player)
-	end
+	CheckProgress(Quest, QuestGiver, Player)
 end
 end
 
 
-function Step2_Complete_Site2(Quest, QuestGiver, Player)
+function Step2Complete(Quest, QuestGiver, Player)
 	UpdateQuestStepDescription(Quest, 2, "I have investigated the ambush site in the area east of Two Logs Pond.")
 	UpdateQuestStepDescription(Quest, 2, "I have investigated the ambush site in the area east of Two Logs Pond.")
-
-	if QuestIsComplete(Player, 217) then
-		Multiple_Steps_Complete(Quest, QuestGiver, Player)
-	end
+	CheckProgress(Quest, QuestGiver, Player)
 end
 end
 
 
-function Step3_Complete_Site3(Quest, QuestGiver, Player)
+function Step3Complete(Quest, QuestGiver, Player)
 	UpdateQuestStepDescription(Quest, 3, "I have investigated the ambush site in the southern end of the area east of Two Logs Pond.")
 	UpdateQuestStepDescription(Quest, 3, "I have investigated the ambush site in the southern end of the area east of Two Logs Pond.")
-	
-	if QuestIsComplete(Player, 217) then
-		Multiple_Steps_Complete(Quest, QuestGiver, Player)
-	end
-end
-
-function Multiple_Steps_Complete(Quest, QuestGiver, Player)
-	UpdateQuestTaskGroupDescription(Quest, 1, "I have investigated all three ambush sites.")
-	
-	-- a gnoll paw
-	if not HasItem(Player, 1711) then
-		SummonItem(Player, 1711)
-		SendMessage(Player, "You receieve [a gnoll paw].", "yellow")
-	end
-
-	AddQuestStepChat(Quest, 4, "I need to return to Lieutenant Dawson.", 1, "I need to tell Lieutenant Dawson of what I found at one of the ambush sites.", 0, 1980022) 
-	AddQuestStepCompleteAction(Quest, 4, "QuestComplete")
+	CheckProgress(Quest, QuestGiver, Player)
 end
 end
 
 
 function QuestComplete(Quest, QuestGiver, Player)
 function QuestComplete(Quest, QuestGiver, Player)
-	-- a gnoll paw
-	while HasItem(Player, 1711) do
-		RemoveItem(Player, 1711)
-	end
-	
+	-- The following UpdateQuestStepDescription and UpdateTaskGroupDescription are not needed, parser adds them for completion in case stuff needs to be moved around
+	UpdateQuestStepDescription(Quest, 4, "I have spoken with Lieutenant Dawson.")
+	UpdateQuestTaskGroupDescription(Quest, 2, "I have spoken with Lieutenant Dawson.")
+
 	UpdateQuestDescription(Quest, "I found evidence of gnolls at one of the ambush sites.")
 	UpdateQuestDescription(Quest, "I found evidence of gnolls at one of the ambush sites.")
 	GiveQuestReward(Quest, Player)
 	GiveQuestReward(Quest, Player)
 end
 end
 
 
 function Reload(Quest, QuestGiver, Player, Step)
 function Reload(Quest, QuestGiver, Player, Step)
 	if Step == 1 then
 	if Step == 1 then
-		Step1_Complete_Site1(Quest, QuestGiver, Player)
+		Step1Complete(Quest, QuestGiver, Player)
 	elseif Step == 2 then
 	elseif Step == 2 then
-		Step2_Complete_Site2(Quest, QuestGiver, Player)
+		Step2Complete(Quest, QuestGiver, Player)
 	elseif Step == 3 then
 	elseif Step == 3 then
-		Step3_Complete_Site3(Quest, QuestGiver, Player)
+		Step3Complete(Quest, QuestGiver, Player)
+	elseif Step == 4 then
+		QuestComplete(Quest, QuestGiver, Player)
 	end
 	end
 end
 end
+
+function Accepted(Quest, QuestGiver, Player)
+	-- Add dialog here for when the quest is accepted
+end
+
+function Declined(Quest, QuestGiver, Player)
+	-- Add dialog here for when the quest is declined
+end

+ 9 - 8
server/SpawnStructs.xml

@@ -375,7 +375,7 @@
 <Data ElementName="hide_health" Type="int8" Size="1" /> <!-- 39 -->
 <Data ElementName="hide_health" Type="int8" Size="1" /> <!-- 39 -->
 <Data ElementName="is_transport" Type="int8" Size="1" /> <!-- 40 -->
 <Data ElementName="is_transport" Type="int8" Size="1" /> <!-- 40 -->
 <Data ElementName="house_icon" Type="int8" Size="1" /> <!-- 41 -->
 <Data ElementName="house_icon" Type="int8" Size="1" /> <!-- 41 -->
-<Data ElementName="in_combat" Type="int8" Size="1" /> <!-- 42 -->
+<Data ElementName="loot_icon" Type="int8" Size="1" /> <!-- 42 -->
 <Data ElementName="afk" Type="int8" Size="1" /> <!-- 43 -->
 <Data ElementName="afk" Type="int8" Size="1" /> <!-- 43 -->
 <Data ElementName="roleplaying" Type="int8" Size="1" /> <!-- 44 -->
 <Data ElementName="roleplaying" Type="int8" Size="1" /> <!-- 44 -->
 <Data ElementName="anonymous" Type="int8" Size="1" /> <!-- 45 -->
 <Data ElementName="anonymous" Type="int8" Size="1" /> <!-- 45 -->
@@ -455,9 +455,9 @@
 <Data ElementName="unknown6" Type="int8" Size="1" /> <!-- 299 -->
 <Data ElementName="unknown6" Type="int8" Size="1" /> <!-- 299 -->
 <Data ElementName="heroic_flag" Type="int8" Size="1" /> <!-- 300 -->
 <Data ElementName="heroic_flag" Type="int8" Size="1" /> <!-- 300 -->
 <Data ElementName="npc" Type="int8" Size="1" /> <!-- 301 -->
 <Data ElementName="npc" Type="int8" Size="1" /> <!-- 301 -->
-<Data ElementName="unknown7" Type="int8" Size="1" /> <!-- 303 -->
-<Data ElementName="unknown8" Type="int8" Size="1" /> <!-- 303 -->
-<Data ElementName="merchant" Type="int8" Size="1" /> <!-- 304 -->
+<Data ElementName="unknown7" Type="int8" Size="1" /> <!-- 302 -->
+<Data ElementName="merchant" Type="int8" Size="1" /> <!-- 303 -->
+<Data ElementName="unknown8" Type="int8" Size="1" /> <!-- 304 -->
 <Data ElementName="unknown9" Type="int8" Size="1" /> <!-- 305 -->
 <Data ElementName="unknown9" Type="int8" Size="1" /> <!-- 305 -->
 <Data ElementName="unknown10" Type="int8" Size="1" /> <!-- 306 -->
 <Data ElementName="unknown10" Type="int8" Size="1" /> <!-- 306 -->
 <Data ElementName="no_arrow_color_or_highlight" Type="int8" Size="1" /> <!-- 307 -->
 <Data ElementName="no_arrow_color_or_highlight" Type="int8" Size="1" /> <!-- 307 -->
@@ -466,7 +466,7 @@
 <Data ElementName="hide_health" Type="int8" Size="1" /> <!-- 310 -->
 <Data ElementName="hide_health" Type="int8" Size="1" /> <!-- 310 -->
 <Data ElementName="is_transport" Type="int8" Size="1" /> <!-- 311 -->
 <Data ElementName="is_transport" Type="int8" Size="1" /> <!-- 311 -->
 <Data ElementName="house_icon" Type="int8" Size="1" /> <!-- 312 -->
 <Data ElementName="house_icon" Type="int8" Size="1" /> <!-- 312 -->
-<Data ElementName="in_combat" Type="int8" Size="1" /> <!-- 313 -->
+<Data ElementName="loot_icon" Type="int8" Size="1" /> <!-- 313 -->
 <Data ElementName="afk" Type="int8" Size="1" /> <!-- 314 -->
 <Data ElementName="afk" Type="int8" Size="1" /> <!-- 314 -->
 <Data ElementName="roleplaying" Type="int8" Size="1" /> <!-- 315 -->
 <Data ElementName="roleplaying" Type="int8" Size="1" /> <!-- 315 -->
 <Data ElementName="anonymous" Type="int8" Size="1" /> <!-- 316 -->
 <Data ElementName="anonymous" Type="int8" Size="1" /> <!-- 316 -->
@@ -554,7 +554,8 @@
 <Data ElementName="mood_state" Type="int16" Size="1" /> <!-- 1083 -->
 <Data ElementName="mood_state" Type="int16" Size="1" /> <!-- 1083 -->
 <Data ElementName="emote_state" Type="int16" Size="1" /> <!-- 1085 -->
 <Data ElementName="emote_state" Type="int16" Size="1" /> <!-- 1085 -->
 <Data ElementName="race" Type="int8" Size="1" /> <!-- 1087 -->
 <Data ElementName="race" Type="int8" Size="1" /> <!-- 1087 -->
-<Data ElementName="gender" Type="int8" Size="1" /> <!-- 1088 --></Struct>
+<Data ElementName="gender" Type="int8" Size="1" /> <!-- 1088 -->
+</Struct>
 <Struct Name="Substruct_SpawnInfoStruct" ClientVersion="547" >
 <Struct Name="Substruct_SpawnInfoStruct" ClientVersion="547" >
 <Data ElementName="hp_remaining" Type="int8" Size="1" />
 <Data ElementName="hp_remaining" Type="int8" Size="1" />
 <Data ElementName="unknown2a" Type="int8" Size="3" />
 <Data ElementName="unknown2a" Type="int8" Size="3" />
@@ -2505,7 +2506,7 @@
 <Data ElementName="red_glow" Type="int8" Size="1" />
 <Data ElementName="red_glow" Type="int8" Size="1" />
 <Data ElementName="show_name" Type="int8" Size="1" />
 <Data ElementName="show_name" Type="int8" Size="1" />
 <Data ElementName="attackable" Type="int8" Size="1" />
 <Data ElementName="attackable" Type="int8" Size="1" />
-<Data ElementName="unknown10" Type="int8" Size="1" />
+<Data ElementName="attackable_icon" Type="int8" Size="1" />
 <Data ElementName="unknown11" Type="int8" Size="1" />
 <Data ElementName="unknown11" Type="int8" Size="1" />
 <Data ElementName="unknown12" Type="int8" Size="1" />
 <Data ElementName="unknown12" Type="int8" Size="1" />
 </Struct>
 </Struct>
@@ -2520,7 +2521,7 @@
 <Data ElementName="red_glow" Type="int8" Size="1" />
 <Data ElementName="red_glow" Type="int8" Size="1" />
 <Data ElementName="show_name" Type="int8" Size="1" />
 <Data ElementName="show_name" Type="int8" Size="1" />
 <Data ElementName="attackable" Type="int8" Size="1" />
 <Data ElementName="attackable" Type="int8" Size="1" />
-<Data ElementName="unknown2" Type="int8" Size="1" />
+<Data ElementName="attackable_icon" Type="int8" Size="1" />
 <Data ElementName="unknown3" Type="int8" Size="1" />
 <Data ElementName="unknown3" Type="int8" Size="1" />
 <Data ElementName="unknown4" Type="int8" Size="1" />
 <Data ElementName="unknown4" Type="int8" Size="1" />
 <Data ElementName="unknown5" Type="int8" Size="1" />
 <Data ElementName="unknown5" Type="int8" Size="1" />

+ 10 - 3
server/WorldStructs.xml

@@ -358,6 +358,9 @@ to zero and treated like placeholders." />
 <Data ElementName="completed_voice_key1" Type="int32" Size="1" />
 <Data ElementName="completed_voice_key1" Type="int32" Size="1" />
 <Data ElementName="completed_voice_key2" Type="int32" Size="1" />
 <Data ElementName="completed_voice_key2" Type="int32" Size="1" />
 </Struct>
 </Struct>
+<Struct Name="WS_InstructionWindowGoal" ClientVersion="1" OpcodeName="OP_ClientCmdMsg" OpcodeType="OP_EqInstructionWindowGoalCmd">
+<Data ElementName="goal_num" Type="int8" Size="1" />
+</Struct>
 <Struct Name="WS_OnScreenMsg" ClientVersion="1" OpcodeName="OP_OnscreenMsgMsg">
 <Struct Name="WS_OnScreenMsg" ClientVersion="1" OpcodeName="OP_OnscreenMsgMsg">
 <Data ElementName="text" Type="EQ2_16Bit_String" />
 <Data ElementName="text" Type="EQ2_16Bit_String" />
 <Data ElementName="message_type" Type="EQ2_16Bit_String" />
 <Data ElementName="message_type" Type="EQ2_16Bit_String" />
@@ -366,7 +369,7 @@ to zero and treated like placeholders." />
 <Data ElementName="green" Type="int8" Size="1" />
 <Data ElementName="green" Type="int8" Size="1" />
 <Data ElementName="blue" Type="int8" Size="1" />
 <Data ElementName="blue" Type="int8" Size="1" />
 </Struct>
 </Struct>
-<Struct Name="WS_OnScreenMsg" ClientVersion="547" OpcodeName="OP_OnscreenMsgMsg">
+<Struct Name="WS_OnScreenMsg" ClientVersion="546" OpcodeName="OP_OnscreenMsgMsg">
 <Data ElementName="unknown" Type="int8" Size="1" />
 <Data ElementName="unknown" Type="int8" Size="1" />
 <Data ElementName="text" Type="EQ2_16Bit_String" />
 <Data ElementName="text" Type="EQ2_16Bit_String" />
 <Data ElementName="message_type" Type="EQ2_16Bit_String" />
 <Data ElementName="message_type" Type="EQ2_16Bit_String" />
@@ -6970,7 +6973,10 @@ to zero and treated like placeholders." />
 <Data ElementName="unknown4" Type="int8" Size="1" />
 <Data ElementName="unknown4" Type="int8" Size="1" />
 <Data ElementName="unknown5" Type="int8" Size="1" />
 <Data ElementName="unknown5" Type="int8" Size="1" />
 </Struct>
 </Struct>
-<Struct Name="WS_CloseWindow" ClientVersion="1" OpcodeName="OP_ClientCmdMsg" OpcodeType="OP_EqCloseWindowCmd" >
+<Struct Name="WS_StoppedLooting" ClientVersion="1" OpcodeName="OP_StoppedLootingMsg" >
+<Data ElementName="spawn_id" Type="int32" />
+</Struct>
+<Struct Name="WS_CloseWindow" ClientVersion="547" OpcodeName="OP_ClientCmdMsg" OpcodeType="OP_EqCloseWindowCmd" >
 <Data ElementName="window_id" Type="int16" />
 <Data ElementName="window_id" Type="int16" />
 <Data ElementName="index" Type="int8" />
 <Data ElementName="index" Type="int8" />
 </Struct>
 </Struct>
@@ -7116,7 +7122,8 @@ to zero and treated like placeholders." />
 	<Data ElementName="difficulty" Type="int8" Size="1" />
 	<Data ElementName="difficulty" Type="int8" Size="1" />
 	<Data ElementName="visible" Type="int8" Size="1" />
 	<Data ElementName="visible" Type="int8" Size="1" />
 </Data>
 </Data>
-<Data ElementName="unknown3" Type="int8" Size="2" />
+<Data ElementName="quest_updated" Type="int8" Size="1" />
+<Data ElementName="collapsed" Type="int8" Size="1" />
 <Data ElementName="visible_quest_id" Type="int32" Size="1" />
 <Data ElementName="visible_quest_id" Type="int32" Size="1" />
 <Data ElementName="player_crc" Type="int32" Size="1" />
 <Data ElementName="player_crc" Type="int32" Size="1" />
 <Data ElementName="player_name" Type="EQ2_16Bit_String" Size="1" />
 <Data ElementName="player_name" Type="EQ2_16Bit_String" Size="1" />

Some files were not shown because too many files changed in this diff