mirror of
https://github.com/EQEmu/Server.git
synced 2026-09-03 01:06:36 +00:00
svn -> git Migration
This commit is contained in:
+1968
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,185 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
|
||||
SET(zone_sources
|
||||
AA.cpp
|
||||
aggro.cpp
|
||||
attack.cpp
|
||||
beacon.cpp
|
||||
bonuses.cpp
|
||||
bot.cpp
|
||||
botspellsai.cpp
|
||||
client.cpp
|
||||
client_logs.cpp
|
||||
client_mods.cpp
|
||||
client_packet.cpp
|
||||
client_process.cpp
|
||||
command.cpp
|
||||
doors.cpp
|
||||
effects.cpp
|
||||
embparser.cpp
|
||||
embperl.cpp
|
||||
embxs.cpp
|
||||
entity.cpp
|
||||
exp.cpp
|
||||
faction.cpp
|
||||
fearpath.cpp
|
||||
forage.cpp
|
||||
groups.cpp
|
||||
guild.cpp
|
||||
guild_mgr.cpp
|
||||
hate_list.cpp
|
||||
horse.cpp
|
||||
inventory.cpp
|
||||
loottables.cpp
|
||||
Map.cpp
|
||||
merc.cpp
|
||||
mob.cpp
|
||||
MobAI.cpp
|
||||
net.cpp
|
||||
npc.cpp
|
||||
NpcAI.cpp
|
||||
Object.cpp
|
||||
parser.cpp
|
||||
pathing.cpp
|
||||
perl_client.cpp
|
||||
perl_doors.cpp
|
||||
perl_entity.cpp
|
||||
perl_groups.cpp
|
||||
perl_hateentry.cpp
|
||||
perl_mob.cpp
|
||||
perl_npc.cpp
|
||||
perl_object.cpp
|
||||
perl_perlpacket.cpp
|
||||
perl_PlayerCorpse.cpp
|
||||
perl_questitem.cpp
|
||||
perl_raids.cpp
|
||||
perlpacket.cpp
|
||||
perlparser.cpp
|
||||
petitions.cpp
|
||||
pets.cpp
|
||||
PlayerCorpse.cpp
|
||||
QGlobals.cpp
|
||||
questmgr.cpp
|
||||
QuestParserCollection.cpp
|
||||
raids.cpp
|
||||
spawn2.cpp
|
||||
spawn2.h
|
||||
spawngroup.cpp
|
||||
spdat.cpp
|
||||
special_attacks.cpp
|
||||
spell_effects.cpp
|
||||
spells.cpp
|
||||
tasks.cpp
|
||||
titles.cpp
|
||||
tradeskills.cpp
|
||||
trading.cpp
|
||||
trap.cpp
|
||||
tribute.cpp
|
||||
updatemgr.cpp
|
||||
watermap.cpp
|
||||
waypoints.cpp
|
||||
worldserver.cpp
|
||||
zone.cpp
|
||||
zone_logsys.cpp
|
||||
zone_profile.cpp
|
||||
ZoneConfig.cpp
|
||||
zonedb.cpp
|
||||
zonedbasync.cpp
|
||||
zoning.cpp
|
||||
)
|
||||
|
||||
SET(zone_headers
|
||||
AA.h
|
||||
basic_functions.h
|
||||
beacon.h
|
||||
blah.h
|
||||
bot.h
|
||||
botStructs.h
|
||||
client.h
|
||||
client_logs.h
|
||||
client_packet.h
|
||||
command.h
|
||||
common.h
|
||||
doors.h
|
||||
embparser.h
|
||||
embperl.h
|
||||
embxs.h
|
||||
entity.h
|
||||
errmsg.h
|
||||
event_codes.h
|
||||
faction.h
|
||||
features.h
|
||||
forage.h
|
||||
groups.h
|
||||
guild_mgr.h
|
||||
hate_list.h
|
||||
horse.h
|
||||
loottable.h
|
||||
map.h
|
||||
masterentity.h
|
||||
maxskill.h
|
||||
message.h
|
||||
merc.h
|
||||
mob.h
|
||||
net.h
|
||||
npc.h
|
||||
NpcAI.h
|
||||
object.h
|
||||
parser.h
|
||||
pathing.h
|
||||
perlpacket.h
|
||||
perlparser.h
|
||||
petitions.h
|
||||
pets.h
|
||||
PlayerCorpse.h
|
||||
QGlobals.h
|
||||
QuestInterface.h
|
||||
questmgr.h
|
||||
QuestParserCollection.h
|
||||
raid.h
|
||||
raids.h
|
||||
skills.h
|
||||
spawn2.cpp
|
||||
spawn2.h
|
||||
spawngroup.h
|
||||
spdat.h
|
||||
StringIDs.h
|
||||
tasks.h
|
||||
titles.h
|
||||
trap.h
|
||||
updatemgr.h
|
||||
watermap.h
|
||||
worldserver.h
|
||||
zone.h
|
||||
zone_profile.h
|
||||
ZoneConfig.h
|
||||
zonedb.h
|
||||
zonedbasync.h
|
||||
zonedump.h
|
||||
)
|
||||
|
||||
ADD_EXECUTABLE(zone ${zone_sources} ${zone_headers})
|
||||
|
||||
ADD_DEFINITIONS(-DZONE)
|
||||
|
||||
TARGET_LINK_LIBRARIES(zone Common ${PERL_LIBRARY} debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE})
|
||||
|
||||
IF(MSVC)
|
||||
SET_TARGET_PROPERTIES(zone PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF")
|
||||
TARGET_LINK_LIBRARIES(zone "Ws2_32.lib")
|
||||
ENDIF(MSVC)
|
||||
|
||||
IF(MINGW)
|
||||
TARGET_LINK_LIBRARIES(zone "WS2_32")
|
||||
ENDIF(MINGW)
|
||||
|
||||
IF(UNIX)
|
||||
TARGET_LINK_LIBRARIES(zone "dl")
|
||||
TARGET_LINK_LIBRARIES(zone "z")
|
||||
TARGET_LINK_LIBRARIES(zone "m")
|
||||
TARGET_LINK_LIBRARIES(zone "rt")
|
||||
TARGET_LINK_LIBRARIES(zone "pthread")
|
||||
ADD_DEFINITIONS(-fPIC)
|
||||
ENDIF(UNIX)
|
||||
|
||||
SET(EXECUTABLE_OUTPUT_PATH ../Bin)
|
||||
+1029
File diff suppressed because it is too large
Load Diff
+2419
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,41 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef NPCAI_H
|
||||
#define NPCAI_H
|
||||
#include "../common/types.h"
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Even con color is wrong and so is the message but i can't seem to find it with a for loop.
|
||||
Seems more like a bitwise comparison client side..
|
||||
con->level = 2; // GREEN
|
||||
con->level = 18; // LIGHT BLUE
|
||||
con->level = 4; // BLUE
|
||||
con->level = 20; // EVEN
|
||||
con->level = 15; // YELLOW
|
||||
con->level = 13; // RED
|
||||
*/
|
||||
#define DEFAULT_AGGRORADIUS 70
|
||||
#define DEFAULT_FRENYRADIUS 70
|
||||
#define MAX_SHIELDRADIUS 20
|
||||
|
||||
uint32 GetLevelCon(uint8 PlayerLevel, uint8 NPCLevel);
|
||||
|
||||
#endif
|
||||
+950
@@ -0,0 +1,950 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "../common/debug.h"
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "masterentity.h"
|
||||
#include "zonedb.h"
|
||||
#include "../common/packet_functions.h"
|
||||
#include "../common/packet_dump.h"
|
||||
#include "../common/MiscFunctions.h"
|
||||
#include "features.h"
|
||||
#include "StringIDs.h"
|
||||
using namespace std;
|
||||
|
||||
#include "QuestParserCollection.h"
|
||||
|
||||
const char DEFAULT_OBJECT_NAME[] = "IT63_ACTORDEF";
|
||||
const char DEFAULT_OBJECT_NAME_SUFFIX[] = "_ACTORDEF";
|
||||
|
||||
|
||||
extern Zone* zone;
|
||||
extern EntityList entity_list;
|
||||
|
||||
// Loading object from database
|
||||
Object::Object(uint32 id, uint32 type, uint32 icon, const Object_Struct& object, const ItemInst* inst)
|
||||
: respawn_timer(0), decay_timer(300000)
|
||||
{
|
||||
|
||||
user = NULL;
|
||||
last_user = NULL;
|
||||
|
||||
// Initialize members
|
||||
m_id = id;
|
||||
m_type = type;
|
||||
m_icon = icon;
|
||||
m_inuse = false;
|
||||
m_inst = NULL;
|
||||
m_ground_spawn=false;
|
||||
// Copy object data
|
||||
memcpy(&m_data, &object, sizeof(Object_Struct));
|
||||
if (inst) {
|
||||
m_inst = inst->Clone();
|
||||
decay_timer.Start();
|
||||
} else {
|
||||
decay_timer.Disable();
|
||||
}
|
||||
respawn_timer.Disable();
|
||||
|
||||
// Set drop_id to zero - it will be set when added to zone with SetID()
|
||||
m_data.drop_id = 0;
|
||||
}
|
||||
|
||||
//creating a re-ocurring ground spawn.
|
||||
Object::Object(const ItemInst* inst, char* name,float max_x,float min_x,float max_y,float min_y,float z,float heading,uint32 respawntimer)
|
||||
: respawn_timer(respawntimer), decay_timer(300000)
|
||||
{
|
||||
|
||||
user = NULL;
|
||||
last_user = NULL;
|
||||
m_max_x=max_x;
|
||||
m_max_y=max_y;
|
||||
m_min_x=min_x;
|
||||
m_min_y=min_y;
|
||||
m_id = 0;
|
||||
m_inst = (inst) ? inst->Clone() : NULL;
|
||||
m_type = OT_DROPPEDITEM;
|
||||
m_icon = 0;
|
||||
m_inuse = false;
|
||||
m_ground_spawn = true;
|
||||
decay_timer.Disable();
|
||||
// Set as much struct data as we can
|
||||
memset(&m_data, 0, sizeof(Object_Struct));
|
||||
m_data.heading = heading;
|
||||
//printf("Spawning object %s at %f,%f,%f\n",name,m_data.x,m_data.y,m_data.z);
|
||||
m_data.z = z;
|
||||
m_data.zone_id = zone->GetZoneID();
|
||||
respawn_timer.Disable();
|
||||
strcpy(m_data.object_name, name);
|
||||
RandomSpawn(false);
|
||||
|
||||
// Hardcoded portion for unknown members
|
||||
m_data.unknown024 = 0x7f001194;
|
||||
m_data.unknown076 = 0x0000d5fe;
|
||||
m_data.unknown084 = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
// Loading object from client dropping item on ground
|
||||
Object::Object(Client* client, const ItemInst* inst)
|
||||
: respawn_timer(0), decay_timer(300000)
|
||||
{
|
||||
user = NULL;
|
||||
last_user = NULL;
|
||||
|
||||
// Initialize members
|
||||
m_id = 0;
|
||||
m_inst = (inst) ? inst->Clone() : NULL;
|
||||
m_type = OT_DROPPEDITEM;
|
||||
m_icon = 0;
|
||||
m_inuse = false;
|
||||
m_ground_spawn = false;
|
||||
// Set as much struct data as we can
|
||||
memset(&m_data, 0, sizeof(Object_Struct));
|
||||
m_data.heading = client->GetHeading();
|
||||
m_data.x = client->GetX();
|
||||
m_data.y = client->GetY();
|
||||
m_data.z = client->GetZ();
|
||||
m_data.zone_id = zone->GetZoneID();
|
||||
|
||||
decay_timer.Start();
|
||||
respawn_timer.Disable();
|
||||
|
||||
// Hardcoded portion for unknown members
|
||||
m_data.unknown024 = 0x7f001194;
|
||||
m_data.unknown076 = 0x0000d5fe;
|
||||
m_data.unknown084 = 0xFFFFFFFF;
|
||||
|
||||
// Set object name
|
||||
if (inst) {
|
||||
const Item_Struct* item = inst->GetItem();
|
||||
if (item && item->IDFile) {
|
||||
if (strlen(item->IDFile) == 0) {
|
||||
strcpy(m_data.object_name, DEFAULT_OBJECT_NAME);
|
||||
}
|
||||
else {
|
||||
// Object name is idfile + _ACTORDEF
|
||||
uint32 len_idfile = strlen(inst->GetItem()->IDFile);
|
||||
uint32 len_copy = sizeof(m_data.object_name) - len_idfile - 1;
|
||||
if (len_copy > sizeof(DEFAULT_OBJECT_NAME_SUFFIX)) {
|
||||
len_copy = sizeof(DEFAULT_OBJECT_NAME_SUFFIX);
|
||||
}
|
||||
|
||||
memcpy(&m_data.object_name[0], inst->GetItem()->IDFile, len_idfile);
|
||||
memcpy(&m_data.object_name[len_idfile], DEFAULT_OBJECT_NAME_SUFFIX, len_copy);
|
||||
}
|
||||
}
|
||||
else {
|
||||
strcpy(m_data.object_name, DEFAULT_OBJECT_NAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Object::Object(const ItemInst *inst, float x, float y, float z, float heading, uint32 decay_time)
|
||||
: respawn_timer(0), decay_timer(decay_time)
|
||||
{
|
||||
user = NULL;
|
||||
last_user = NULL;
|
||||
|
||||
// Initialize members
|
||||
m_id = 0;
|
||||
m_inst = (inst) ? inst->Clone() : NULL;
|
||||
m_type = OT_DROPPEDITEM;
|
||||
m_icon = 0;
|
||||
m_inuse = false;
|
||||
m_ground_spawn = false;
|
||||
// Set as much struct data as we can
|
||||
memset(&m_data, 0, sizeof(Object_Struct));
|
||||
m_data.heading = heading;
|
||||
m_data.x = x;
|
||||
m_data.y = y;
|
||||
m_data.z = z;
|
||||
m_data.zone_id = zone->GetZoneID();
|
||||
|
||||
if (decay_time)
|
||||
decay_timer.Start();
|
||||
|
||||
respawn_timer.Disable();
|
||||
|
||||
// Hardcoded portion for unknown members
|
||||
m_data.unknown024 = 0x7f001194;
|
||||
m_data.unknown076 = 0x0000d5fe;
|
||||
m_data.unknown084 = 0xFFFFFFFF;
|
||||
|
||||
// Set object name
|
||||
if (inst) {
|
||||
const Item_Struct* item = inst->GetItem();
|
||||
if (item && item->IDFile) {
|
||||
if (strlen(item->IDFile) == 0) {
|
||||
strcpy(m_data.object_name, DEFAULT_OBJECT_NAME);
|
||||
}
|
||||
else {
|
||||
// Object name is idfile + _ACTORDEF
|
||||
uint32 len_idfile = strlen(inst->GetItem()->IDFile);
|
||||
uint32 len_copy = sizeof(m_data.object_name) - len_idfile - 1;
|
||||
if (len_copy > sizeof(DEFAULT_OBJECT_NAME_SUFFIX)) {
|
||||
len_copy = sizeof(DEFAULT_OBJECT_NAME_SUFFIX);
|
||||
}
|
||||
|
||||
memcpy(&m_data.object_name[0], inst->GetItem()->IDFile, len_idfile);
|
||||
memcpy(&m_data.object_name[len_idfile], DEFAULT_OBJECT_NAME_SUFFIX, len_copy);
|
||||
}
|
||||
}
|
||||
else {
|
||||
strcpy(m_data.object_name, DEFAULT_OBJECT_NAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Object::Object(const char *model, float x, float y, float z, float heading, uint8 type, uint32 decay_time)
|
||||
: respawn_timer(0), decay_timer(decay_time)
|
||||
{
|
||||
user = NULL;
|
||||
last_user = NULL;
|
||||
ItemInst* inst = NULL;
|
||||
inst = new ItemInst(ItemUseWorldContainer);
|
||||
|
||||
// Initialize members
|
||||
m_id = 0;
|
||||
m_inst = (inst) ? inst->Clone() : NULL;
|
||||
m_type = type;
|
||||
m_icon = 0;
|
||||
m_inuse = false;
|
||||
m_ground_spawn = false;
|
||||
// Set as much struct data as we can
|
||||
memset(&m_data, 0, sizeof(Object_Struct));
|
||||
m_data.heading = heading;
|
||||
m_data.x = x;
|
||||
m_data.y = y;
|
||||
m_data.z = z;
|
||||
m_data.zone_id = zone->GetZoneID();
|
||||
|
||||
if (decay_time)
|
||||
decay_timer.Start();
|
||||
|
||||
respawn_timer.Disable();
|
||||
|
||||
//Hardcoded portion for unknown members
|
||||
m_data.unknown024 = 0x7f001194;
|
||||
m_data.unknown076 = 0x0000d5fe;
|
||||
m_data.unknown084 = 0xFFFFFFFF;
|
||||
|
||||
if(model)
|
||||
strcpy(m_data.object_name, model);
|
||||
else
|
||||
strcpy(m_data.object_name, "IT64_ACTORDEF"); //default object name if model isn't specified for some unknown reason
|
||||
}
|
||||
|
||||
Object::~Object()
|
||||
{
|
||||
safe_delete(m_inst);
|
||||
if(user != NULL) {
|
||||
user->SetTradeskillObject(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void Object::SetID(uint16 set_id)
|
||||
{
|
||||
// Invoke base class
|
||||
Entity::SetID(set_id);
|
||||
|
||||
// Store new id as drop_id
|
||||
m_data.drop_id = (uint32)this->GetID();
|
||||
}
|
||||
|
||||
// Reset state of object back to zero
|
||||
void Object::ResetState()
|
||||
{
|
||||
safe_delete(m_inst);
|
||||
|
||||
m_id = 0;
|
||||
m_type = 0;
|
||||
m_icon = 0;
|
||||
memset(&m_data, 0, sizeof(Object_Struct));
|
||||
}
|
||||
|
||||
bool Object::Save()
|
||||
{
|
||||
if (m_id) {
|
||||
// Update existing
|
||||
database.UpdateObject(m_id, m_type, m_icon, m_data, m_inst);
|
||||
}
|
||||
else {
|
||||
// Doesn't yet exist, add now
|
||||
m_id = database.AddObject(m_type, m_icon, m_data, m_inst);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16 Object::VarSave()
|
||||
{
|
||||
if (m_id) {
|
||||
// Update existing
|
||||
database.UpdateObject(m_id, m_type, m_icon, m_data, m_inst);
|
||||
}
|
||||
else {
|
||||
// Doesn't yet exist, add now
|
||||
m_id = database.AddObject(m_type, m_icon, m_data, m_inst);
|
||||
}
|
||||
return m_id;
|
||||
}
|
||||
|
||||
// Remove object from database
|
||||
void Object::Delete(bool reset_state)
|
||||
{
|
||||
if (m_id != 0) {
|
||||
database.DeleteObject(m_id);
|
||||
}
|
||||
|
||||
if (reset_state) {
|
||||
ResetState();
|
||||
}
|
||||
}
|
||||
|
||||
// Add item to object (only logical for world tradeskill containers
|
||||
void Object::PutItem(uint8 index, const ItemInst* inst)
|
||||
{
|
||||
if (index > 9) {
|
||||
LogFile->write(EQEMuLog::Error, "Object::PutItem: Invalid index specified (%i)", index);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_inst && m_inst->IsType(ItemClassContainer)) {
|
||||
if (inst) {
|
||||
m_inst->PutItem(index, *inst);
|
||||
}
|
||||
else {
|
||||
m_inst->DeleteItem(index);
|
||||
}
|
||||
database.SaveWorldContainer(zone->GetZoneID(),m_id,m_inst);
|
||||
// This is _highly_ inefficient, but for now it will work: Save entire object to database
|
||||
Save();
|
||||
}
|
||||
}
|
||||
|
||||
void Object::Close() {
|
||||
m_inuse = false;
|
||||
if(user != NULL)
|
||||
{
|
||||
last_user = user;
|
||||
// put any remaining items from the world container back into the player's inventory to avoid item loss
|
||||
// if they close the container without removing all items
|
||||
ItemInst* container = this->m_inst;
|
||||
if(container != NULL)
|
||||
{
|
||||
for (uint8 i = 0; i < MAX_ITEMS_PER_BAG; i++)
|
||||
{
|
||||
ItemInst* inst = container->PopItem(i);
|
||||
if(inst != NULL)
|
||||
{
|
||||
user->MoveItemToInventory(inst, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
user->SetTradeskillObject(NULL);
|
||||
}
|
||||
user = NULL;
|
||||
}
|
||||
|
||||
// Remove item from container
|
||||
void Object::DeleteItem(uint8 index)
|
||||
{
|
||||
if (m_inst && m_inst->IsType(ItemClassContainer)) {
|
||||
m_inst->DeleteItem(index);
|
||||
|
||||
// This is _highly_ inefficient, but for now it will work: Save entire object to database
|
||||
Save();
|
||||
}
|
||||
}
|
||||
|
||||
// Pop item out of container
|
||||
ItemInst* Object::PopItem(uint8 index)
|
||||
{
|
||||
ItemInst* inst = NULL;
|
||||
|
||||
if (m_inst && m_inst->IsType(ItemClassContainer)) {
|
||||
inst = m_inst->PopItem(index);
|
||||
|
||||
// This is _highly_ inefficient, but for now it will work: Save entire object to database
|
||||
Save();
|
||||
}
|
||||
|
||||
return inst;
|
||||
}
|
||||
|
||||
void Object::CreateSpawnPacket(EQApplicationPacket* app)
|
||||
{
|
||||
app->SetOpcode(OP_GroundSpawn);
|
||||
app->pBuffer = new uchar[sizeof(Object_Struct)];
|
||||
app->size = sizeof(Object_Struct);
|
||||
memcpy(app->pBuffer, &m_data, sizeof(Object_Struct));
|
||||
}
|
||||
|
||||
void Object::CreateDeSpawnPacket(EQApplicationPacket* app)
|
||||
{
|
||||
app->SetOpcode(OP_ClickObject);
|
||||
app->pBuffer = new uchar[sizeof(ClickObject_Struct)];
|
||||
app->size = sizeof(ClickObject_Struct);
|
||||
memset(app->pBuffer, 0, sizeof(ClickObject_Struct));
|
||||
ClickObject_Struct* co = (ClickObject_Struct*) app->pBuffer;
|
||||
co->drop_id = m_data.drop_id;
|
||||
co->player_id = 0;
|
||||
}
|
||||
|
||||
bool Object::Process(){
|
||||
if(m_type == OT_DROPPEDITEM && decay_timer.Enabled() && decay_timer.Check()) {
|
||||
// Send click to all clients (removes entity on client)
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_ClickObject, sizeof(ClickObject_Struct));
|
||||
ClickObject_Struct* click_object = (ClickObject_Struct*)outapp->pBuffer;
|
||||
click_object->drop_id = GetID();
|
||||
entity_list.QueueClients(NULL, outapp, false);
|
||||
safe_delete(outapp);
|
||||
|
||||
// Remove object
|
||||
database.DeleteObject(m_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(m_ground_spawn && respawn_timer.Check()){
|
||||
RandomSpawn(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Object::RandomSpawn(bool send_packet) {
|
||||
if(!m_ground_spawn)
|
||||
return;
|
||||
|
||||
m_data.x = MakeRandomFloat(m_min_x, m_max_x);
|
||||
m_data.y = MakeRandomFloat(m_min_y, m_max_y);
|
||||
respawn_timer.Disable();
|
||||
|
||||
if(send_packet) {
|
||||
EQApplicationPacket app;
|
||||
CreateSpawnPacket(&app);
|
||||
entity_list.QueueClients(NULL, &app, true);
|
||||
}
|
||||
}
|
||||
|
||||
bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object)
|
||||
{
|
||||
if(m_ground_spawn){//This is a Cool Groundspawn
|
||||
respawn_timer.Start();
|
||||
}
|
||||
if (m_type == OT_DROPPEDITEM) {
|
||||
bool cursordelete = false;
|
||||
if (m_inst && sender) {
|
||||
// if there is a lore conflict, delete the offending item from the server inventory
|
||||
// the client updates itself and takes care of sending "duplicate lore item" messages
|
||||
if(sender->CheckLoreConflict(m_inst->GetItem())) {
|
||||
int16 loreslot = sender->GetInv().HasItem(m_inst->GetItem()->ID, 0, invWhereBank);
|
||||
if(loreslot != SLOT_INVALID) // if the duplicate is in the bank, delete it.
|
||||
sender->DeleteItemInInventory(loreslot);
|
||||
else
|
||||
cursordelete = true; // otherwise, we delete the new one
|
||||
}
|
||||
|
||||
char buf[10];
|
||||
snprintf(buf, 9, "%u", m_inst->GetItem()->ID);
|
||||
buf[9] = '\0';
|
||||
parse->EventPlayer(EVENT_PLAYER_PICKUP, sender, buf, 0);
|
||||
|
||||
// Transfer item to client
|
||||
sender->PutItemInInventory(SLOT_CURSOR, *m_inst, false);
|
||||
sender->SendItemPacket(SLOT_CURSOR, m_inst, ItemPacketTrade);
|
||||
|
||||
if(cursordelete) // delete the item if it's a duplicate lore. We have to do this because the client expects the item packet
|
||||
sender->DeleteItemInInventory(SLOT_CURSOR);
|
||||
|
||||
if(!m_ground_spawn)
|
||||
safe_delete(m_inst);
|
||||
|
||||
// No longer using a tradeskill object
|
||||
sender->SetTradeskillObject(NULL);
|
||||
user = NULL;
|
||||
}
|
||||
|
||||
// Send click to all clients (removes entity on client)
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_ClickObject, sizeof(ClickObject_Struct));
|
||||
memcpy(outapp->pBuffer, click_object, sizeof(ClickObject_Struct));
|
||||
entity_list.QueueClients(NULL, outapp, false);
|
||||
safe_delete(outapp);
|
||||
|
||||
// Remove object
|
||||
database.DeleteObject(m_id);
|
||||
if(!m_ground_spawn)
|
||||
entity_list.RemoveEntity(this->GetID());
|
||||
} else {
|
||||
// Tradeskill item
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_ClickObjectAction, sizeof(ClickObjectAction_Struct));
|
||||
ClickObjectAction_Struct* coa = (ClickObjectAction_Struct*)outapp->pBuffer;
|
||||
|
||||
//TODO: there is prolly a better way to do this.
|
||||
//if this is not the main user, send them a close and a message
|
||||
if(user == NULL || user == sender)
|
||||
coa->open = 0x01;
|
||||
else {
|
||||
coa->open = 0x00;
|
||||
//sender->Message(13, "Somebody is allready using that container.");
|
||||
}
|
||||
m_inuse = true;
|
||||
coa->type = m_type;
|
||||
coa->unknown16 = 0x0a;
|
||||
|
||||
coa->drop_id = click_object->drop_id;
|
||||
coa->player_id = click_object->player_id;
|
||||
coa->icon = m_icon;
|
||||
|
||||
if(sender->IsLooting())
|
||||
{
|
||||
coa->open = 0x00;
|
||||
user = sender;
|
||||
}
|
||||
|
||||
sender->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
|
||||
//if the object allready had a user, we are done
|
||||
if(user != NULL)
|
||||
return(false);
|
||||
|
||||
// Starting to use this object
|
||||
sender->SetTradeskillObject(this);
|
||||
|
||||
user = sender;
|
||||
|
||||
// Send items inside of container
|
||||
|
||||
if (m_inst && m_inst->IsType(ItemClassContainer)) {
|
||||
|
||||
//Clear out no-drop and no-rent items first if different player opens it
|
||||
if(user != last_user)
|
||||
m_inst->ClearByFlags(byFlagSet, byFlagSet);
|
||||
|
||||
EQApplicationPacket* outapp=new EQApplicationPacket(OP_ClientReady,0);
|
||||
sender->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
for (uint8 i=0; i<10; i++) {
|
||||
const ItemInst* inst = m_inst->GetItem(i);
|
||||
if (inst) {
|
||||
//sender->GetInv().PutItem(i+4000,inst);
|
||||
sender->SendItemPacket(i, inst, ItemPacketWorldContainer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Add new Zone Object (theoretically only called for items dropped to ground)
|
||||
uint32 ZoneDatabase::AddObject(uint32 type, uint32 icon, const Object_Struct& object, const ItemInst* inst)
|
||||
{
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
|
||||
uint32 database_id = 0;
|
||||
uint32 item_id = 0;
|
||||
int16 charges = 0;
|
||||
|
||||
if (inst && inst->GetItem()) {
|
||||
item_id = inst->GetItem()->ID;
|
||||
charges = inst->GetCharges();
|
||||
}
|
||||
|
||||
// SQL Escape object_name
|
||||
uint32 len = strlen(object.object_name) * 2 + 1;
|
||||
char* object_name = new char[len];
|
||||
DoEscapeString(object_name, object.object_name, strlen(object.object_name));
|
||||
|
||||
// Construct query
|
||||
uint32 len_query = MakeAnyLenString(&query,
|
||||
"insert into object (zoneid, xpos, ypos, zpos, heading, itemid, charges, objectname, "
|
||||
"type, icon) values (%i, %f, %f, %f, %f, %i, %i, '%s', %i, %i)",
|
||||
object.zone_id, object.x, object.y, object.z, object.heading,
|
||||
item_id, charges, object_name, type, icon);
|
||||
|
||||
// Save new record for object
|
||||
if (!RunQuery(query, len_query, errbuf, NULL, NULL, &database_id)) {
|
||||
LogFile->write(EQEMuLog::Error, "Unable to insert object: %s", errbuf);
|
||||
}
|
||||
else {
|
||||
// Save container contents, if container
|
||||
if (inst && inst->IsType(ItemClassContainer)) {
|
||||
SaveWorldContainer(object.zone_id, database_id, inst);
|
||||
}
|
||||
}
|
||||
|
||||
safe_delete_array(object_name);
|
||||
safe_delete_array(query);
|
||||
return database_id;
|
||||
}
|
||||
|
||||
// Update information about existing object in database
|
||||
void ZoneDatabase::UpdateObject(uint32 id, uint32 type, uint32 icon, const Object_Struct& object, const ItemInst* inst)
|
||||
{
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
|
||||
uint32 item_id = 0;
|
||||
int16 charges = 0;
|
||||
|
||||
if (inst && inst->GetItem()) {
|
||||
item_id = inst->GetItem()->ID;
|
||||
charges = inst->GetCharges();
|
||||
}
|
||||
|
||||
// SQL Escape object_name
|
||||
uint32 len = strlen(object.object_name) * 2 + 1;
|
||||
char* object_name = new char[len];
|
||||
DoEscapeString(object_name, object.object_name, strlen(object.object_name));
|
||||
|
||||
// Construct query
|
||||
uint32 len_query = MakeAnyLenString(&query,
|
||||
"update object set zoneid=%i, xpos=%f, ypos=%f, zpos=%f, heading=%f, "
|
||||
"itemid=%i, charges=%i, objectname='%s', type=%i, icon=%i where id=%i",
|
||||
object.zone_id, object.x, object.y, object.z, object.heading,
|
||||
item_id, charges, object_name, type, icon, id);
|
||||
|
||||
// Save new record for object
|
||||
if (!RunQuery(query, len_query, errbuf)) {
|
||||
LogFile->write(EQEMuLog::Error, "Unable to update object: %s", errbuf);
|
||||
}
|
||||
else {
|
||||
// Save container contents, if container
|
||||
if (inst && inst->IsType(ItemClassContainer)) {
|
||||
SaveWorldContainer(object.zone_id, id, inst);
|
||||
}
|
||||
}
|
||||
|
||||
safe_delete_array(object_name);
|
||||
safe_delete_array(query);
|
||||
}
|
||||
Ground_Spawns* ZoneDatabase::LoadGroundSpawns(uint32 zone_id, int16 version, Ground_Spawns* gs){
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT max_x,max_y,max_z,min_x,min_y,heading,name,item,max_allowed,respawn_timer from ground_spawns where zoneid=%i and (version=%u OR version=-1) limit 50", zone_id, version), errbuf, &result))
|
||||
{
|
||||
safe_delete_array(query);
|
||||
int i=0;
|
||||
while( (row=mysql_fetch_row(result) ) ) {
|
||||
gs->spawn[i].max_x=atof(row[0]);
|
||||
gs->spawn[i].max_y=atof(row[1]);
|
||||
gs->spawn[i].max_z=atof(row[2]);
|
||||
gs->spawn[i].min_x=atof(row[3]);
|
||||
gs->spawn[i].min_y=atof(row[4]);
|
||||
gs->spawn[i].heading=atof(row[5]);
|
||||
strcpy(gs->spawn[i].name,row[6]);
|
||||
gs->spawn[i].item=atoi(row[7]);
|
||||
gs->spawn[i].max_allowed=atoi(row[8]);
|
||||
gs->spawn[i].respawntimer=atoi(row[9]);
|
||||
i++;
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else {
|
||||
cerr << "Error in LoadGroundSpawns query '" << query << "' " << errbuf << endl;
|
||||
safe_delete_array(query);
|
||||
}
|
||||
return gs;
|
||||
}
|
||||
void ZoneDatabase::DeleteObject(uint32 id)
|
||||
{
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
|
||||
// Construct query
|
||||
uint32 len_query = MakeAnyLenString(&query,
|
||||
"delete from object where id=%i", id);
|
||||
|
||||
// Save new record for object
|
||||
if (!RunQuery(query, len_query, errbuf)) {
|
||||
LogFile->write(EQEMuLog::Error, "Unable to delete object: %s", errbuf);
|
||||
}
|
||||
//else {
|
||||
// Delete contained items, if any
|
||||
// DeleteWorldContainer(id);
|
||||
//}
|
||||
|
||||
safe_delete_array(query);
|
||||
}
|
||||
|
||||
uint32 Object::GetDBID()
|
||||
{
|
||||
return this->m_id;
|
||||
}
|
||||
|
||||
uint32 Object::GetType()
|
||||
{
|
||||
return this->m_type;
|
||||
}
|
||||
|
||||
void Object::SetType(uint32 type)
|
||||
{
|
||||
this->m_type = type;
|
||||
this->m_data.object_type = type;
|
||||
}
|
||||
|
||||
uint32 Object::GetIcon()
|
||||
{
|
||||
return this->m_icon;
|
||||
}
|
||||
|
||||
float Object::GetX()
|
||||
{
|
||||
return this->m_data.x;
|
||||
}
|
||||
|
||||
float Object::GetY()
|
||||
{
|
||||
return this->m_data.y;
|
||||
}
|
||||
|
||||
|
||||
float Object::GetZ()
|
||||
{
|
||||
return this->m_data.z;
|
||||
}
|
||||
|
||||
float Object::GetHeadingData()
|
||||
{
|
||||
return this->m_data.heading;
|
||||
}
|
||||
|
||||
void Object::SetX(float pos)
|
||||
{
|
||||
this->m_data.x = pos;
|
||||
|
||||
EQApplicationPacket* app = new EQApplicationPacket();
|
||||
EQApplicationPacket* app2 = new EQApplicationPacket();
|
||||
this->CreateDeSpawnPacket(app);
|
||||
this->CreateSpawnPacket(app2);
|
||||
entity_list.QueueClients(0, app);
|
||||
entity_list.QueueClients(0, app2);
|
||||
safe_delete(app);
|
||||
safe_delete(app2);
|
||||
}
|
||||
|
||||
void Object::SetY(float pos)
|
||||
{
|
||||
this->m_data.y = pos;
|
||||
|
||||
EQApplicationPacket* app = new EQApplicationPacket();
|
||||
EQApplicationPacket* app2 = new EQApplicationPacket();
|
||||
this->CreateDeSpawnPacket(app);
|
||||
this->CreateSpawnPacket(app2);
|
||||
entity_list.QueueClients(0, app);
|
||||
entity_list.QueueClients(0, app2);
|
||||
safe_delete(app);
|
||||
safe_delete(app2);
|
||||
}
|
||||
|
||||
void Object::Depop()
|
||||
{
|
||||
EQApplicationPacket* app = new EQApplicationPacket();
|
||||
this->CreateDeSpawnPacket(app);
|
||||
entity_list.QueueClients(0, app);
|
||||
safe_delete(app);
|
||||
entity_list.RemoveObject(this->GetID());
|
||||
}
|
||||
|
||||
void Object::Repop()
|
||||
{
|
||||
EQApplicationPacket* app = new EQApplicationPacket();
|
||||
EQApplicationPacket* app2 = new EQApplicationPacket();
|
||||
this->CreateDeSpawnPacket(app);
|
||||
this->CreateSpawnPacket(app2);
|
||||
entity_list.QueueClients(0, app);
|
||||
entity_list.QueueClients(0, app2);
|
||||
safe_delete(app);
|
||||
safe_delete(app2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Object::SetZ(float pos)
|
||||
{
|
||||
this->m_data.z = pos;
|
||||
|
||||
EQApplicationPacket* app = new EQApplicationPacket();
|
||||
EQApplicationPacket* app2 = new EQApplicationPacket();
|
||||
this->CreateDeSpawnPacket(app);
|
||||
this->CreateSpawnPacket(app2);
|
||||
entity_list.QueueClients(0, app);
|
||||
entity_list.QueueClients(0, app2);
|
||||
safe_delete(app);
|
||||
safe_delete(app2);
|
||||
}
|
||||
|
||||
void Object::SetModelName(const char* modelname)
|
||||
{
|
||||
strn0cpy(m_data.object_name, modelname, sizeof(m_data.object_name)); // 32 is the max for chars in object_name, this should be safe
|
||||
EQApplicationPacket* app = new EQApplicationPacket();
|
||||
EQApplicationPacket* app2 = new EQApplicationPacket();
|
||||
this->CreateDeSpawnPacket(app);
|
||||
this->CreateSpawnPacket(app2);
|
||||
entity_list.QueueClients(0, app);
|
||||
entity_list.QueueClients(0, app2);
|
||||
safe_delete(app);
|
||||
safe_delete(app2);
|
||||
}
|
||||
|
||||
const char* Object::GetModelName()
|
||||
{
|
||||
return this->m_data.object_name;
|
||||
}
|
||||
|
||||
void Object::SetIcon(uint32 icon)
|
||||
{
|
||||
this->m_icon = icon;
|
||||
}
|
||||
|
||||
uint32 Object::GetItemID()
|
||||
{
|
||||
if (this->m_inst == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Item_Struct* item = this->m_inst->GetItem();
|
||||
|
||||
if (item == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return item->ID;
|
||||
}
|
||||
|
||||
void Object::SetItemID(uint32 itemid)
|
||||
{
|
||||
safe_delete(this->m_inst);
|
||||
|
||||
if (itemid)
|
||||
{
|
||||
this->m_inst = database.CreateItem(itemid);
|
||||
}
|
||||
}
|
||||
|
||||
void Object::GetObjectData(Object_Struct* Data)
|
||||
{
|
||||
if (Data)
|
||||
{
|
||||
memcpy(Data, &this->m_data, sizeof(this->m_data));
|
||||
}
|
||||
}
|
||||
|
||||
void Object::SetObjectData(Object_Struct* Data)
|
||||
{
|
||||
if (Data)
|
||||
{
|
||||
memcpy(&this->m_data, Data, sizeof(this->m_data));
|
||||
}
|
||||
}
|
||||
|
||||
void Object::GetLocation(float* x, float* y, float* z)
|
||||
{
|
||||
if (x)
|
||||
{
|
||||
*x = this->m_data.x;
|
||||
}
|
||||
|
||||
if (y)
|
||||
{
|
||||
*y = this->m_data.y;
|
||||
}
|
||||
|
||||
if (z)
|
||||
{
|
||||
*z = this->m_data.z;
|
||||
}
|
||||
}
|
||||
|
||||
void Object::SetLocation(float x, float y, float z)
|
||||
{
|
||||
this->m_data.x = x;
|
||||
this->m_data.y = y;
|
||||
this->m_data.z = z;
|
||||
EQApplicationPacket* app = new EQApplicationPacket();
|
||||
EQApplicationPacket* app2 = new EQApplicationPacket();
|
||||
this->CreateDeSpawnPacket(app);
|
||||
this->CreateSpawnPacket(app2);
|
||||
entity_list.QueueClients(0, app);
|
||||
entity_list.QueueClients(0, app2);
|
||||
safe_delete(app);
|
||||
safe_delete(app2);
|
||||
}
|
||||
|
||||
void Object::GetHeading(float* heading)
|
||||
{
|
||||
if (heading)
|
||||
{
|
||||
*heading = this->m_data.heading;
|
||||
}
|
||||
}
|
||||
|
||||
void Object::SetHeading(float heading)
|
||||
{
|
||||
this->m_data.heading = heading;
|
||||
EQApplicationPacket* app = new EQApplicationPacket();
|
||||
EQApplicationPacket* app2 = new EQApplicationPacket();
|
||||
this->CreateDeSpawnPacket(app);
|
||||
this->CreateSpawnPacket(app2);
|
||||
entity_list.QueueClients(0, app);
|
||||
entity_list.QueueClients(0, app2);
|
||||
safe_delete(app);
|
||||
safe_delete(app2);
|
||||
}
|
||||
|
||||
void Object::SetEntityVariable(const char *id, const char *m_var)
|
||||
{
|
||||
std::string n_m_var = m_var;
|
||||
o_EntityVariables[id] = n_m_var;
|
||||
}
|
||||
|
||||
const char* Object::GetEntityVariable(const char *id)
|
||||
{
|
||||
if(!id)
|
||||
return NULL;
|
||||
|
||||
std::map<std::string, std::string>::iterator iter = o_EntityVariables.find(id);
|
||||
if(iter != o_EntityVariables.end())
|
||||
{
|
||||
return iter->second.c_str();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool Object::EntityVariableExists(const char * id)
|
||||
{
|
||||
if(!id)
|
||||
return false;
|
||||
|
||||
std::map<std::string, std::string>::iterator iter = o_EntityVariables.find(id);
|
||||
if(iter != o_EntityVariables.end())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,142 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef CORPSE_H
|
||||
#define CORPSE_H
|
||||
|
||||
#include "mob.h"
|
||||
|
||||
class Client;
|
||||
class NPC;
|
||||
|
||||
#define MAX_LOOTERS 72
|
||||
|
||||
class Corpse : public Mob
|
||||
{
|
||||
public:
|
||||
static void SendEndLootErrorPacket(Client* client);
|
||||
static void SendLootReqErrorPacket(Client* client, uint8 response = 2);
|
||||
static Corpse* LoadFromDBData(uint32 in_corpseid, uint32 in_charid, char* in_charname, uchar* in_data, uint32 in_datasize, float in_x, float in_y, float in_z, float in_heading, char* timeofdeath, bool rezzed = false, bool wasAtGraveyard = false);
|
||||
|
||||
Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NPCType** in_npctypedata, uint32 in_decaytime = 600000);
|
||||
Corpse(Client* client, int32 in_rezexp);
|
||||
Corpse(uint32 in_corpseid, uint32 in_charid, char* in_charname, ItemList* in_itemlist, uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_plat, float in_x, float in_y, float in_z, float in_heading, float in_size, uint8 in_gender, uint16 in_race, uint8 in_class, uint8 in_deity, uint8 in_level, uint8 in_texture, uint8 in_helmtexture,uint32 in_rezexp, bool wasAtGraveyard = false);
|
||||
~Corpse();
|
||||
|
||||
//abstract virtual function implementations requird by base abstract class
|
||||
virtual void Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillType attack_skill) { return; }
|
||||
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false) { return; }
|
||||
virtual bool Attack(Mob* other, int Hand = 13, bool FromRiposte = false, bool IsStrikethrough = true, bool IsFromSpell = false) { return false; }
|
||||
virtual bool HasRaid() { return false; }
|
||||
virtual bool HasGroup() { return false; }
|
||||
virtual Raid* GetRaid() { return 0; }
|
||||
virtual Group* GetGroup() { return 0; }
|
||||
|
||||
void LoadPlayerCorpseDecayTime(uint32 dbid);
|
||||
|
||||
bool IsCorpse() const { return true; }
|
||||
bool IsPlayerCorpse() const { return p_PlayerCorpse; }
|
||||
bool IsNPCCorpse() const { return !p_PlayerCorpse; }
|
||||
bool IsBecomeNPCCorpse() const { return become_npc; }
|
||||
bool Process();
|
||||
bool Save();
|
||||
uint32 GetCharID() { return charid; }
|
||||
uint32 SetCharID(uint32 iCharID) { if (IsPlayerCorpse()) { return (charid=iCharID); } return 0xFFFFFFFF; };
|
||||
uint32 GetDecayTime() { if (!corpse_decay_timer.Enabled()) return 0xFFFFFFFF; else return corpse_decay_timer.GetRemainingTime(); }
|
||||
uint32 GetResTime() { if (!corpse_res_timer.Enabled()) return 0; else return corpse_res_timer.GetRemainingTime(); }
|
||||
void CalcCorpseName();
|
||||
inline void Lock() { pLocked = true; }
|
||||
inline void UnLock() { pLocked = false; }
|
||||
inline bool IsLocked() { return pLocked; }
|
||||
inline void ResetLooter() { BeingLootedBy = 0xFFFFFFFF; }
|
||||
inline bool IsBeingLooted() { return (BeingLootedBy != 0xFFFFFFFF); }
|
||||
inline uint32 GetDBID() { return dbid; }
|
||||
inline char* GetOwnerName() { return orgname;}
|
||||
|
||||
void SetDecayTimer(uint32 decaytime);
|
||||
bool IsEmpty() const;
|
||||
void AddItem(uint32 itemnum, uint16 charges, int16 slot = 0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0);
|
||||
uint32 GetWornItem(int16 equipSlot) const;
|
||||
ServerLootItem_Struct* GetItem(uint16 lootslot, ServerLootItem_Struct** bag_item_data = 0);
|
||||
void RemoveItem(uint16 lootslot);
|
||||
void RemoveItem(ServerLootItem_Struct* item_data);
|
||||
void SetCash(uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_platinum);
|
||||
void RemoveCash();
|
||||
void QueryLoot(Client* to);
|
||||
uint32 CountItems();
|
||||
void Delete();
|
||||
void Bury();
|
||||
virtual void Depop();
|
||||
virtual void DepopCorpse();
|
||||
|
||||
uint32 GetCopper() { return copper; }
|
||||
uint32 GetSilver() { return silver; }
|
||||
uint32 GetGold() { return gold; }
|
||||
uint32 GetPlatinum() { return platinum; }
|
||||
|
||||
void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
|
||||
void MakeLootRequestPackets(Client* client, const EQApplicationPacket* app);
|
||||
void LootItem(Client* client, const EQApplicationPacket* app);
|
||||
void EndLoot(Client* client, const EQApplicationPacket* app);
|
||||
bool Summon(Client* client, bool spell, bool CheckDistance);
|
||||
void CastRezz(uint16 spellid, Mob* Caster);
|
||||
void CompleteRezz();
|
||||
void SetPKItem(int32 id) { pkitem = id; }
|
||||
int32 GetPKItem() { return pkitem; }
|
||||
bool CanMobLoot(int charid);
|
||||
void AllowMobLoot(Mob *them, uint8 slot);
|
||||
void AddLooter(Mob *who);
|
||||
bool Rezzed() { return rez; }
|
||||
void Rezzed(bool in_rez) { rez = in_rez; }
|
||||
void Spawn();
|
||||
|
||||
char orgname[64];
|
||||
uint32 GetEquipment(uint8 material_slot) const; // returns item id
|
||||
uint32 GetEquipmentColor(uint8 material_slot) const;
|
||||
inline int GetRezzExp() { return rezzexp; }
|
||||
|
||||
protected:
|
||||
std::list<uint32> MoveItemToCorpse(Client *client, ItemInst *item, int16 equipslot);
|
||||
|
||||
private:
|
||||
bool p_PlayerCorpse; bool pIsChanged;
|
||||
bool pLocked;
|
||||
int32 pkitem;
|
||||
uint32 dbid;
|
||||
uint32 charid;
|
||||
ItemList itemlist;
|
||||
uint32 copper;
|
||||
uint32 silver;
|
||||
uint32 gold;
|
||||
uint32 platinum;
|
||||
bool p_depop;
|
||||
uint32 BeingLootedBy;
|
||||
uint32 rezzexp;
|
||||
bool rez;
|
||||
bool can_rez;
|
||||
bool become_npc;
|
||||
int looters[MAX_LOOTERS]; // People allowed to loot the corpse, character id
|
||||
Timer corpse_decay_timer;
|
||||
Timer corpse_res_timer;
|
||||
Timer corpse_delay_timer;
|
||||
Timer corpse_graveyard_timer;
|
||||
Timer loot_cooldown_timer;
|
||||
Color_Struct item_tint[9];
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,138 @@
|
||||
#include "../common/debug.h"
|
||||
#include "../common/MiscFunctions.h"
|
||||
#include "QGlobals.h"
|
||||
#include "zonedb.h"
|
||||
|
||||
void QGlobalCache::AddGlobal(uint32 id, QGlobal global)
|
||||
{
|
||||
global.id = id;
|
||||
qGlobalBucket.push_back(global);
|
||||
}
|
||||
|
||||
void QGlobalCache::RemoveGlobal(std::string name, uint32 npcID, uint32 charID, uint32 zoneID)
|
||||
{
|
||||
std::list<QGlobal>::iterator iter = qGlobalBucket.begin();
|
||||
while(iter != qGlobalBucket.end())
|
||||
{
|
||||
if(name.compare((*iter).name) == 0)
|
||||
{
|
||||
if((npcID == (*iter).npc_id || (*iter).npc_id == 0) && (charID == (*iter).char_id || (*iter).char_id == 0) && (zoneID == (*iter).zone_id || (*iter).zone_id == 0))
|
||||
{
|
||||
qGlobalBucket.erase(iter);
|
||||
return;
|
||||
}
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
void QGlobalCache::Combine(std::list<QGlobal> &cacheA, std::list<QGlobal> cacheB, uint32 npcID, uint32 charID, uint32 zoneID)
|
||||
{
|
||||
std::list<QGlobal>::iterator iter = cacheB.begin();
|
||||
while(iter != cacheB.end())
|
||||
{
|
||||
QGlobal cur = (*iter);
|
||||
|
||||
if((cur.npc_id == npcID || cur.npc_id == 0) && (cur.char_id == charID || cur.char_id == 0) && (cur.zone_id == zoneID || cur.zone_id == 0))
|
||||
{
|
||||
if(Timer::GetTimeSeconds() < cur.expdate)
|
||||
{
|
||||
cacheA.push_back(cur);
|
||||
}
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
void QGlobalCache::PurgeExpiredGlobals()
|
||||
{
|
||||
if(!qGlobalBucket.size())
|
||||
return;
|
||||
|
||||
std::list<QGlobal>::iterator iter = qGlobalBucket.begin();
|
||||
while(iter != qGlobalBucket.end())
|
||||
{
|
||||
QGlobal cur = (*iter);
|
||||
if(Timer::GetTimeSeconds() > cur.expdate)
|
||||
{
|
||||
iter = qGlobalBucket.erase(iter);
|
||||
continue;
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
void QGlobalCache::LoadByNPCID(uint32 npcID)
|
||||
{
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (database.RunQuery(query, MakeAnyLenString(&query, "select name, charid, npcid, zoneid, value, expdate"
|
||||
" from quest_globals where npcid = %d", npcID), errbuf, &result))
|
||||
{
|
||||
while((row = mysql_fetch_row(result)))
|
||||
{
|
||||
AddGlobal(0, QGlobal(std::string(row[0]), atoi(row[1]), atoi(row[2]), atoi(row[3]), row[4], row[5]?atoi(row[5]):0xFFFFFFFF));
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
safe_delete_array(query);
|
||||
}
|
||||
|
||||
void QGlobalCache::LoadByCharID(uint32 charID)
|
||||
{
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (database.RunQuery(query, MakeAnyLenString(&query, "select name, charid, npcid, zoneid, value, expdate from"
|
||||
" quest_globals where charid = %d && npcid = 0", charID), errbuf, &result))
|
||||
{
|
||||
while((row = mysql_fetch_row(result)))
|
||||
{
|
||||
AddGlobal(0, QGlobal(std::string(row[0]), atoi(row[1]), atoi(row[2]), atoi(row[3]), row[4], row[5]?atoi(row[5]):0xFFFFFFFF));
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
safe_delete_array(query);
|
||||
}
|
||||
|
||||
void QGlobalCache::LoadByZoneID(uint32 zoneID)
|
||||
{
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (database.RunQuery(query, MakeAnyLenString(&query, "select name, charid, npcid, zoneid, value, expdate from quest_globals"
|
||||
" where zoneid = %d && npcid = 0 && charid = 0", zoneID), errbuf, &result))
|
||||
{
|
||||
while((row = mysql_fetch_row(result)))
|
||||
{
|
||||
AddGlobal(0, QGlobal(std::string(row[0]), atoi(row[1]), atoi(row[2]), atoi(row[3]), row[4], row[5]?atoi(row[5]):0xFFFFFFFF));
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
safe_delete_array(query);
|
||||
}
|
||||
void QGlobalCache::LoadByGlobalContext()
|
||||
{
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (database.RunQuery(query, MakeAnyLenString(&query, "select name, charid, npcid, zoneid, value, expdate from quest_globals"
|
||||
" where zoneid = 0 && npcid = 0 && charid = 0"), errbuf, &result))
|
||||
{
|
||||
while((row = mysql_fetch_row(result)))
|
||||
{
|
||||
AddGlobal(0, QGlobal(std::string(row[0]), atoi(row[1]), atoi(row[2]), atoi(row[3]), row[4], row[5]?atoi(row[5]):0xFFFFFFFF));
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
safe_delete_array(query);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#ifndef __QGLOBALS__H
|
||||
#define __QGLOBALS__H
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <stdlib.h>
|
||||
#include "../common/timer.h"
|
||||
|
||||
struct QGlobal
|
||||
{
|
||||
QGlobal() { }
|
||||
QGlobal(std::string g_name, uint32 c_id, uint32 n_id, uint32 z_id, std::string n_value, uint32 expire_date)
|
||||
: name(g_name), char_id(c_id), npc_id(n_id), zone_id(z_id), value(n_value), expdate(expire_date) { id = 0; }
|
||||
std::string name;
|
||||
uint32 char_id;
|
||||
uint32 npc_id;
|
||||
uint32 zone_id;
|
||||
std::string value;
|
||||
uint32 expdate;
|
||||
uint32 id;
|
||||
};
|
||||
|
||||
class QGlobalCache
|
||||
{
|
||||
public:
|
||||
void AddGlobal(uint32 id, QGlobal global);
|
||||
void RemoveGlobal(std::string name, uint32 npcID, uint32 charID, uint32 zoneID);
|
||||
std::list<QGlobal> GetBucket() { return qGlobalBucket; }
|
||||
|
||||
//assumes cacheA is already a valid or empty list and doesn't check for valid items.
|
||||
static void Combine(std::list<QGlobal> &cacheA, std::list<QGlobal> cacheB, uint32 npcID, uint32 charID, uint32 zoneID);
|
||||
|
||||
void PurgeExpiredGlobals();
|
||||
void LoadByNPCID(uint32 npcID); //npc
|
||||
void LoadByCharID(uint32 charID); //client
|
||||
void LoadByZoneID(uint32 zoneID); //zone
|
||||
void LoadByGlobalContext(); //zone
|
||||
protected:
|
||||
std::list<QGlobal> qGlobalBucket;
|
||||
};
|
||||
|
||||
#endif
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "../common/debug.h"
|
||||
#include <iostream.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// Disgrace: for windows compile
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#define snprintf _snprintf
|
||||
#else
|
||||
#include "../common/unix.h"
|
||||
#endif
|
||||
|
||||
#include "Quest.h"
|
||||
|
||||
pquest_entry Quest::m_pQuests;
|
||||
int Quest::m_nQuests;
|
||||
|
||||
Quest::Quest()
|
||||
{
|
||||
m_pQuests = NULL;
|
||||
m_nQuests = 0;
|
||||
}
|
||||
|
||||
Quest::~Quest()
|
||||
{
|
||||
for( int i=0;i<m_nQuests;i++ )
|
||||
{
|
||||
delete m_pQuests[ i ].m_pQuestName;
|
||||
delete m_pQuests[ i ].m_pQuestText;
|
||||
delete m_pQuests[ i ].m_pQuestEnd;
|
||||
}
|
||||
delete[] m_pQuests;
|
||||
}
|
||||
|
||||
bool ZoneDatabase::OpenQuery(char* zonename) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
MYSQL_RES* result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT name, text, end, npcID, questobject, priceobject, cash, exp FROM quest WHERE zone='%s'", zonename), errbuf, &result)) {
|
||||
delete[] query;
|
||||
Quest::m_nQuests = mysql_num_rows( result );
|
||||
if( Quest::m_nQuests )
|
||||
{
|
||||
int l_cnt = 0;
|
||||
Quest::m_pQuests = new quest_entry[ Quest::m_nQuests ];
|
||||
while(row = mysql_fetch_row(result)) {
|
||||
Quest::m_pQuests[ l_cnt ].m_pQuestName = new char[ strlen( row[0] )+1 ];
|
||||
strcpy( Quest::m_pQuests[ l_cnt ].m_pQuestName, row[0] );
|
||||
Quest::m_pQuests[ l_cnt ].m_pQuestText = new char[ strlen( row[1] )+1 ];
|
||||
strcpy( Quest::m_pQuests[ l_cnt ].m_pQuestText, row[1] );
|
||||
Quest::m_pQuests[ l_cnt ].m_pQuestEnd = new char[ strlen( row[2] )+1 ];
|
||||
strcpy( Quest::m_pQuests[ l_cnt ].m_pQuestEnd, row[2] );
|
||||
|
||||
Quest::m_pQuests[ l_cnt ].m_iNpcId = atoi( row[3] );
|
||||
Quest::m_pQuests[ l_cnt ].m_iQuestObject= atoi( row[4] );
|
||||
Quest::m_pQuests[ l_cnt ].m_iQuestPrice = atoi( row[5] );
|
||||
Quest::m_pQuests[ l_cnt ].m_iQuestCash = atoi( row[6] );
|
||||
Quest::m_pQuests[ l_cnt ].m_iQuestExp = atoi( row[7] );
|
||||
cerr << "Quests '" << Quest::m_pQuests[ l_cnt ].m_pQuestName << "' , NPCID " << Quest::m_pQuests[ l_cnt ].m_iNpcId << endl;
|
||||
l_cnt++;
|
||||
}
|
||||
mysql_free_result(result);
|
||||
return true;
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
cerr << "Error in ZoneDatabase::OpenQuest query '" << query << "' " << errbuf << endl;
|
||||
delete[] query;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
pquest_entry Quest::Test( int NpcId, int QuestObject )
|
||||
{
|
||||
for( int i=0;i<m_nQuests;i++ )
|
||||
if( m_pQuests[ i ].m_iNpcId == NpcId && m_pQuests[ i ].m_iQuestObject == QuestObject )
|
||||
return &m_pQuests[ i ];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef __QUEST_H__
|
||||
#define __QUEST_H__
|
||||
|
||||
#include "zonedb.h"
|
||||
|
||||
typedef struct _tag_quest_entry{
|
||||
char *m_pQuestName;
|
||||
char *m_pQuestText;
|
||||
char *m_pQuestEnd;
|
||||
int m_iNpcId;
|
||||
int m_iQuestObject;
|
||||
int m_iQuestPrice;
|
||||
int m_iQuestCash;
|
||||
int m_iQuestExp;
|
||||
}quest_entry,*pquest_entry;
|
||||
|
||||
|
||||
class Quest{
|
||||
public:
|
||||
Quest();
|
||||
~Quest();
|
||||
static pquest_entry Test(int NpcId, int QuestObject);
|
||||
|
||||
static pquest_entry m_pQuests;
|
||||
static int m_nQuests;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifndef _EQE_QUESTINTERFACE_H
|
||||
#define _EQE_QUESTINTERFACE_H
|
||||
|
||||
#include "../common/types.h"
|
||||
#include "event_codes.h"
|
||||
|
||||
class ItemInst;
|
||||
class Client;
|
||||
class NPC;
|
||||
|
||||
class QuestInterface {
|
||||
public:
|
||||
virtual void EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data) { }
|
||||
virtual void EventGlobalNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data) { }
|
||||
virtual void EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data) { }
|
||||
virtual void EventGlobalPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data) { }
|
||||
virtual void EventItem(QuestEventID evt, Client *client, ItemInst *item, uint32 objid, uint32 extra_data) { }
|
||||
virtual void EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data) { }
|
||||
|
||||
virtual bool HasQuestSub(uint32 npcid, const char *subname) { return false; }
|
||||
virtual bool HasGlobalQuestSub(const char *subname) { return false; }
|
||||
virtual bool PlayerHasQuestSub(const char *subname) { return false; }
|
||||
virtual bool GlobalPlayerHasQuestSub(const char *subname) { return false; }
|
||||
virtual bool SpellHasQuestSub(uint32 spell_id, const char *subname) { return false; }
|
||||
virtual bool ItemHasQuestSub(ItemInst *itm, const char *subname) { return false; }
|
||||
|
||||
virtual void AddVar(std::string name, std::string val) { }
|
||||
virtual void ReloadQuests(bool reset_timers = true) { }
|
||||
virtual uint32 GetIdentifier() { return 0; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,576 @@
|
||||
#include "../common/debug.h"
|
||||
#include "../common/MiscFunctions.h"
|
||||
#include "QuestParserCollection.h"
|
||||
#include "QuestInterface.h"
|
||||
#include "zone.h"
|
||||
#include "zonedb.h"
|
||||
#include "features.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
extern Zone* zone;
|
||||
|
||||
QuestParserCollection::QuestParserCollection() {
|
||||
_player_quest_status = QuestUnloaded;
|
||||
_global_player_quest_status = QuestUnloaded;
|
||||
}
|
||||
|
||||
QuestParserCollection::~QuestParserCollection() {
|
||||
}
|
||||
|
||||
void QuestParserCollection::RegisterQuestInterface(QuestInterface *qi, std::string ext) {
|
||||
_interfaces[qi->GetIdentifier()] = qi;
|
||||
_extensions[qi->GetIdentifier()] = ext;
|
||||
_load_precedence.push_back(qi);
|
||||
}
|
||||
|
||||
void QuestParserCollection::AddVar(std::string name, std::string val) {
|
||||
std::list<QuestInterface*>::iterator iter = _load_precedence.begin();
|
||||
while(iter != _load_precedence.end()) {
|
||||
(*iter)->AddVar(name, val);
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
void QuestParserCollection::ReloadQuests(bool reset_timers) {
|
||||
_npc_quest_status.clear();
|
||||
_player_quest_status = QuestUnloaded;
|
||||
_global_player_quest_status = QuestUnloaded;
|
||||
_global_npc_quest_status = QuestUnloaded;
|
||||
_spell_quest_status.clear();
|
||||
_item_quest_status.clear();
|
||||
std::list<QuestInterface*>::iterator iter = _load_precedence.begin();
|
||||
while(iter != _load_precedence.end()) {
|
||||
(*iter)->ReloadQuests(reset_timers);
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
bool QuestParserCollection::HasQuestSub(uint32 npcid, const char *subname) {
|
||||
std::map<uint32, uint32>::iterator iter = _npc_quest_status.find(npcid);
|
||||
if(_global_npc_quest_status == QuestUnloaded){
|
||||
QuestInterface *qi = GetQIByGlobalNPCQuest();
|
||||
if(qi) {
|
||||
_global_npc_quest_status = qi->GetIdentifier();
|
||||
return qi->HasGlobalQuestSub(subname);
|
||||
}
|
||||
}
|
||||
if(iter != _npc_quest_status.end()) {
|
||||
//loaded or failed to load
|
||||
if(iter->second != QuestFailedToLoad) {
|
||||
std::map<uint32, QuestInterface*>::iterator qiter = _interfaces.find(iter->second);
|
||||
return qiter->second->HasQuestSub(npcid, subname) || qiter->second->HasGlobalQuestSub(subname);
|
||||
}
|
||||
} else {
|
||||
QuestInterface *qi = GetQIByGlobalNPCQuest();
|
||||
if(qi) {
|
||||
_global_npc_quest_status = qi->GetIdentifier();
|
||||
}
|
||||
|
||||
qi = GetQIByNPCQuest(npcid);
|
||||
if(qi) {
|
||||
_npc_quest_status[npcid] = qi->GetIdentifier();
|
||||
return qi->HasQuestSub(npcid, subname) || qi->HasGlobalQuestSub(subname);
|
||||
} else {
|
||||
_npc_quest_status[npcid] = QuestFailedToLoad;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QuestParserCollection::PlayerHasQuestSub(const char *subname) {
|
||||
if(_player_quest_status == QuestUnloaded) {
|
||||
QuestInterface *qi = GetQIByGlobalPlayerQuest();
|
||||
if(qi) {
|
||||
_global_player_quest_status = qi->GetIdentifier();
|
||||
}
|
||||
|
||||
qi = GetQIByPlayerQuest();
|
||||
if(qi) {
|
||||
_player_quest_status = qi->GetIdentifier();
|
||||
return qi->PlayerHasQuestSub(subname) || qi->GlobalPlayerHasQuestSub(subname);
|
||||
}
|
||||
} else if(_player_quest_status != QuestFailedToLoad) {
|
||||
std::map<uint32, QuestInterface*>::iterator iter = _interfaces.find(_player_quest_status);
|
||||
return iter->second->PlayerHasQuestSub(subname) || iter->second->GlobalPlayerHasQuestSub(subname);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QuestParserCollection::SpellHasQuestSub(uint32 spell_id, const char *subname) {
|
||||
std::map<uint32, uint32>::iterator iter = _spell_quest_status.find(spell_id);
|
||||
if(iter != _spell_quest_status.end()) {
|
||||
//loaded or failed to load
|
||||
if(iter->second != QuestFailedToLoad) {
|
||||
std::map<uint32, QuestInterface*>::iterator qiter = _interfaces.find(iter->second);
|
||||
return qiter->second->SpellHasQuestSub(spell_id, subname);
|
||||
}
|
||||
} else {
|
||||
QuestInterface *qi = GetQIBySpellQuest(spell_id);
|
||||
if(qi) {
|
||||
_spell_quest_status[spell_id] = qi->GetIdentifier();
|
||||
return qi->SpellHasQuestSub(spell_id, subname);
|
||||
} else {
|
||||
_spell_quest_status[spell_id] = QuestFailedToLoad;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QuestParserCollection::ItemHasQuestSub(ItemInst *itm, const char *subname) {
|
||||
std::string item_script;
|
||||
if(strcmp("EVENT_SCALE_CALC", subname) == 0 || strcmp("EVENT_ITEM_ENTERZONE", subname) == 0) {
|
||||
item_script = itm->GetItem()->CharmFile;
|
||||
} else if(strcmp("EVENT_ITEM_CLICK", subname) == 0 || strcmp("EVENT_ITEM_CLICK_CAST", subname) == 0) {
|
||||
item_script = "script_";
|
||||
item_script += itoa(itm->GetItem()->ScriptFileID);
|
||||
} else {
|
||||
item_script = itoa(itm->GetItem()->ID);
|
||||
}
|
||||
|
||||
std::map<std::string, uint32>::iterator iter = _item_quest_status.find(item_script);
|
||||
if(iter != _item_quest_status.end()) {
|
||||
//loaded or failed to load
|
||||
if(iter->second != QuestFailedToLoad) {
|
||||
std::map<uint32, QuestInterface*>::iterator qiter = _interfaces.find(iter->second);
|
||||
return qiter->second->ItemHasQuestSub(itm, subname);
|
||||
}
|
||||
} else {
|
||||
QuestInterface *qi = GetQIByItemQuest(item_script);
|
||||
if(qi) {
|
||||
_item_quest_status[item_script] = qi->GetIdentifier();
|
||||
return qi->ItemHasQuestSub(itm, subname);
|
||||
} else {
|
||||
_item_quest_status[item_script] = QuestFailedToLoad;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void QuestParserCollection::EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data) {
|
||||
std::map<uint32, uint32>::iterator iter = _npc_quest_status.find(npc->GetNPCTypeID());
|
||||
if(iter != _npc_quest_status.end()) {
|
||||
//loaded or failed to load
|
||||
if(iter->second != QuestFailedToLoad) {
|
||||
std::map<uint32, QuestInterface*>::iterator qiter = _interfaces.find(iter->second);
|
||||
qiter->second->EventNPC(evt, npc, init, data, extra_data);
|
||||
}
|
||||
} else {
|
||||
QuestInterface *qi = GetQIByNPCQuest(npc->GetNPCTypeID());
|
||||
if(qi) {
|
||||
_npc_quest_status[npc->GetNPCTypeID()] = qi->GetIdentifier();
|
||||
qi->EventNPC(evt, npc, init, data, extra_data);
|
||||
} else {
|
||||
_npc_quest_status[npc->GetNPCTypeID()] = QuestFailedToLoad;
|
||||
}
|
||||
}
|
||||
|
||||
// K, lets also parse templates/global_npc.pl
|
||||
if(_global_npc_quest_status != QuestUnloaded) {
|
||||
QuestInterface *qi = GetQIByGlobalNPCQuest();
|
||||
if(qi) {
|
||||
_global_npc_quest_status = qi->GetIdentifier();
|
||||
qi->EventGlobalNPC(evt, npc, init, data, extra_data);
|
||||
}
|
||||
} else {
|
||||
if(_global_npc_quest_status != QuestFailedToLoad) {
|
||||
std::map<uint32, QuestInterface*>::iterator iter = _interfaces.find(_global_npc_quest_status);
|
||||
if(iter != _interfaces.end())
|
||||
iter->second->EventGlobalNPC(evt, npc, init, data, extra_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QuestParserCollection::EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data) {
|
||||
if(_player_quest_status == QuestUnloaded) {
|
||||
QuestInterface *qi = GetQIByGlobalPlayerQuest();
|
||||
if(qi) {
|
||||
_global_player_quest_status = qi->GetIdentifier();
|
||||
qi->EventGlobalPlayer(evt, client, data, extra_data);
|
||||
}
|
||||
|
||||
qi = GetQIByPlayerQuest();
|
||||
if(qi) {
|
||||
_player_quest_status = qi->GetIdentifier();
|
||||
qi->EventPlayer(evt, client, data, extra_data);
|
||||
}
|
||||
|
||||
} else {
|
||||
if(_global_player_quest_status != QuestFailedToLoad) {
|
||||
std::map<uint32, QuestInterface*>::iterator iter = _interfaces.find(_global_player_quest_status);
|
||||
if(iter != _interfaces.end())
|
||||
iter->second->EventGlobalPlayer(evt, client, data, extra_data);
|
||||
}
|
||||
if(_player_quest_status != QuestFailedToLoad) {
|
||||
std::map<uint32, QuestInterface*>::iterator iter = _interfaces.find(_player_quest_status);
|
||||
iter->second->EventPlayer(evt, client, data, extra_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QuestParserCollection::EventItem(QuestEventID evt, Client *client, ItemInst *item, uint32 objid, uint32 extra_data) {
|
||||
std::string item_script;
|
||||
if(evt == EVENT_SCALE_CALC || evt == EVENT_ITEM_ENTERZONE) {
|
||||
item_script = item->GetItem()->CharmFile;
|
||||
} else if(evt == EVENT_ITEM_CLICK || evt == EVENT_ITEM_CLICK_CAST) {
|
||||
item_script = "script_";
|
||||
item_script += itoa(item->GetItem()->ScriptFileID);
|
||||
} else {
|
||||
item_script = itoa(item->GetItem()->ID);
|
||||
}
|
||||
|
||||
std::map<std::string, uint32>::iterator iter = _item_quest_status.find(item_script);
|
||||
if(iter != _item_quest_status.end()) {
|
||||
//loaded or failed to load
|
||||
if(iter->second != QuestFailedToLoad) {
|
||||
std::map<uint32, QuestInterface*>::iterator qiter = _interfaces.find(iter->second);
|
||||
qiter->second->EventItem(evt, client, item, objid, extra_data);
|
||||
}
|
||||
} else {
|
||||
QuestInterface *qi = GetQIByItemQuest(item_script);
|
||||
if(qi) {
|
||||
_item_quest_status[item_script] = qi->GetIdentifier();
|
||||
qi->EventItem(evt, client, item, objid, extra_data);
|
||||
} else {
|
||||
_item_quest_status[item_script] = QuestFailedToLoad;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QuestParserCollection::EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data) {
|
||||
std::map<uint32, uint32>::iterator iter = _spell_quest_status.find(spell_id);
|
||||
if(iter != _spell_quest_status.end()) {
|
||||
//loaded or failed to load
|
||||
if(iter->second != QuestFailedToLoad) {
|
||||
std::map<uint32, QuestInterface*>::iterator qiter = _interfaces.find(iter->second);
|
||||
qiter->second->EventSpell(evt, npc, client, spell_id, extra_data);
|
||||
}
|
||||
} else {
|
||||
QuestInterface *qi = GetQIBySpellQuest(spell_id);
|
||||
if(qi) {
|
||||
_spell_quest_status[spell_id] = qi->GetIdentifier();
|
||||
qi->EventSpell(evt, npc, client, spell_id, extra_data);
|
||||
} else {
|
||||
_spell_quest_status[spell_id] = QuestFailedToLoad;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid) {
|
||||
//first look for /quests/zone/npcid.ext (precedence)
|
||||
std::string filename = "quests/";
|
||||
filename += zone->GetShortName();
|
||||
filename += "/";
|
||||
filename += itoa(npcid);
|
||||
std::string tmp;
|
||||
FILE *f = NULL;
|
||||
|
||||
std::list<QuestInterface*>::iterator iter = _load_precedence.begin();
|
||||
while(iter != _load_precedence.end()) {
|
||||
tmp = filename;
|
||||
std::map<uint32, std::string>::iterator ext = _extensions.find((*iter)->GetIdentifier());
|
||||
tmp += ".";
|
||||
tmp += ext->second;
|
||||
f = fopen(tmp.c_str(), "r");
|
||||
if(f) {
|
||||
fclose(f);
|
||||
return (*iter);
|
||||
}
|
||||
|
||||
iter++;
|
||||
}
|
||||
|
||||
//second look for /quests/zone/npcname.ext (precedence)
|
||||
const NPCType *npc_type = database.GetNPCType(npcid);
|
||||
if(!npc_type) {
|
||||
return NULL;
|
||||
}
|
||||
std::string npc_name = npc_type->name;
|
||||
int sz = static_cast<int>(npc_name.length());
|
||||
for(int i = 0; i < sz; ++i) {
|
||||
if(npc_name[i] == '`') {
|
||||
npc_name[i] = '-';
|
||||
}
|
||||
}
|
||||
|
||||
filename = "quests/";
|
||||
filename += zone->GetShortName();
|
||||
filename += "/";
|
||||
filename += npc_name;
|
||||
|
||||
iter = _load_precedence.begin();
|
||||
while(iter != _load_precedence.end()) {
|
||||
tmp = filename;
|
||||
std::map<uint32, std::string>::iterator ext = _extensions.find((*iter)->GetIdentifier());
|
||||
tmp += ".";
|
||||
tmp += ext->second;
|
||||
f = fopen(tmp.c_str(), "r");
|
||||
if(f) {
|
||||
fclose(f);
|
||||
return (*iter);
|
||||
}
|
||||
|
||||
iter++;
|
||||
}
|
||||
|
||||
//third look for /quests/zone/default.ext (precedence)
|
||||
filename = "quests/";
|
||||
filename += zone->GetShortName();
|
||||
filename += "/";
|
||||
filename += "default";
|
||||
iter = _load_precedence.begin();
|
||||
while(iter != _load_precedence.end()) {
|
||||
tmp = filename;
|
||||
std::map<uint32, std::string>::iterator ext = _extensions.find((*iter)->GetIdentifier());
|
||||
tmp += ".";
|
||||
tmp += ext->second;
|
||||
f = fopen(tmp.c_str(), "r");
|
||||
if(f) {
|
||||
fclose(f);
|
||||
return (*iter);
|
||||
}
|
||||
|
||||
iter++;
|
||||
}
|
||||
|
||||
//fourth look for /quests/templates/npcid.ext (precedence)
|
||||
filename = "quests/";
|
||||
filename += QUEST_TEMPLATES_DIRECTORY;
|
||||
filename += "/";
|
||||
filename += itoa(npcid);
|
||||
iter = _load_precedence.begin();
|
||||
while(iter != _load_precedence.end()) {
|
||||
tmp = filename;
|
||||
std::map<uint32, std::string>::iterator ext = _extensions.find((*iter)->GetIdentifier());
|
||||
tmp += ".";
|
||||
tmp += ext->second;
|
||||
f = fopen(tmp.c_str(), "r");
|
||||
if(f) {
|
||||
fclose(f);
|
||||
return (*iter);
|
||||
}
|
||||
|
||||
iter++;
|
||||
}
|
||||
|
||||
//fifth look for /quests/templates/npcname.ext (precedence)
|
||||
filename = "quests/";
|
||||
filename += QUEST_TEMPLATES_DIRECTORY;
|
||||
filename += "/";
|
||||
filename += npc_name;
|
||||
iter = _load_precedence.begin();
|
||||
while(iter != _load_precedence.end()) {
|
||||
tmp = filename;
|
||||
std::map<uint32, std::string>::iterator ext = _extensions.find((*iter)->GetIdentifier());
|
||||
tmp += ".";
|
||||
tmp += ext->second;
|
||||
f = fopen(tmp.c_str(), "r");
|
||||
if(f) {
|
||||
fclose(f);
|
||||
return (*iter);
|
||||
}
|
||||
|
||||
iter++;
|
||||
}
|
||||
|
||||
//fifth look for /quests/templates/default.ext (precedence)
|
||||
filename = "quests/";
|
||||
filename += QUEST_TEMPLATES_DIRECTORY;
|
||||
filename += "/";
|
||||
filename += "default";
|
||||
iter = _load_precedence.begin();
|
||||
while(iter != _load_precedence.end()) {
|
||||
tmp = filename;
|
||||
std::map<uint32, std::string>::iterator ext = _extensions.find((*iter)->GetIdentifier());
|
||||
tmp += ".";
|
||||
tmp += ext->second;
|
||||
f = fopen(tmp.c_str(), "r");
|
||||
if(f) {
|
||||
fclose(f);
|
||||
return (*iter);
|
||||
}
|
||||
|
||||
iter++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
QuestInterface *QuestParserCollection::GetQIByPlayerQuest() {
|
||||
|
||||
if(!zone)
|
||||
return NULL;
|
||||
|
||||
//first look for /quests/zone/player_v[instance_version].ext (precedence)
|
||||
std::string filename = "quests/";
|
||||
filename += zone->GetShortName();
|
||||
filename += "/";
|
||||
filename += "player_v";
|
||||
filename += itoa(zone->GetInstanceVersion());
|
||||
std::string tmp;
|
||||
FILE *f = NULL;
|
||||
|
||||
std::list<QuestInterface*>::iterator iter = _load_precedence.begin();
|
||||
while(iter != _load_precedence.end()) {
|
||||
tmp = filename;
|
||||
std::map<uint32, std::string>::iterator ext = _extensions.find((*iter)->GetIdentifier());
|
||||
tmp += ".";
|
||||
tmp += ext->second;
|
||||
f = fopen(tmp.c_str(), "r");
|
||||
if(f) {
|
||||
fclose(f);
|
||||
return (*iter);
|
||||
}
|
||||
|
||||
iter++;
|
||||
}
|
||||
|
||||
//second look for /quests/zone/player.ext (precedence)
|
||||
filename = "quests/";
|
||||
filename += zone->GetShortName();
|
||||
filename += "/";
|
||||
filename += "player";
|
||||
|
||||
iter = _load_precedence.begin();
|
||||
while(iter != _load_precedence.end()) {
|
||||
tmp = filename;
|
||||
std::map<uint32, std::string>::iterator ext = _extensions.find((*iter)->GetIdentifier());
|
||||
tmp += ".";
|
||||
tmp += ext->second;
|
||||
f = fopen(tmp.c_str(), "r");
|
||||
if(f) {
|
||||
fclose(f);
|
||||
return (*iter);
|
||||
}
|
||||
|
||||
iter++;
|
||||
}
|
||||
|
||||
//third look for /quests/templates/player.ext (precedence)
|
||||
filename = "quests/";
|
||||
filename += QUEST_TEMPLATES_DIRECTORY;
|
||||
filename += "/";
|
||||
filename += "player";
|
||||
iter = _load_precedence.begin();
|
||||
while(iter != _load_precedence.end()) {
|
||||
tmp = filename;
|
||||
std::map<uint32, std::string>::iterator ext = _extensions.find((*iter)->GetIdentifier());
|
||||
tmp += ".";
|
||||
tmp += ext->second;
|
||||
f = fopen(tmp.c_str(), "r");
|
||||
if(f) {
|
||||
fclose(f);
|
||||
return (*iter);
|
||||
}
|
||||
|
||||
iter++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
QuestInterface *QuestParserCollection::GetQIByGlobalNPCQuest(){
|
||||
// simply look for templates/global_npc.pl
|
||||
std::string filename = "quests/";
|
||||
filename += QUEST_TEMPLATES_DIRECTORY;
|
||||
filename += "/";
|
||||
filename += "global_npc";
|
||||
std::string tmp;
|
||||
FILE *f = NULL;
|
||||
|
||||
std::list<QuestInterface*>::iterator iter = _load_precedence.begin();
|
||||
while(iter != _load_precedence.end()) {
|
||||
tmp = filename;
|
||||
std::map<uint32, std::string>::iterator ext = _extensions.find((*iter)->GetIdentifier());
|
||||
tmp += ".";
|
||||
tmp += ext->second;
|
||||
f = fopen(tmp.c_str(), "r");
|
||||
if(f) {
|
||||
fclose(f);
|
||||
return (*iter);
|
||||
}
|
||||
|
||||
iter++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
QuestInterface *QuestParserCollection::GetQIByGlobalPlayerQuest() {
|
||||
//first look for /quests/templates/player.ext (precedence)
|
||||
std::string filename = "quests/";
|
||||
filename += QUEST_TEMPLATES_DIRECTORY;
|
||||
filename += "/";
|
||||
filename += "global_player";
|
||||
std::string tmp;
|
||||
FILE *f = NULL;
|
||||
|
||||
std::list<QuestInterface*>::iterator iter = _load_precedence.begin();
|
||||
while(iter != _load_precedence.end()) {
|
||||
tmp = filename;
|
||||
std::map<uint32, std::string>::iterator ext = _extensions.find((*iter)->GetIdentifier());
|
||||
tmp += ".";
|
||||
tmp += ext->second;
|
||||
f = fopen(tmp.c_str(), "r");
|
||||
if(f) {
|
||||
fclose(f);
|
||||
return (*iter);
|
||||
}
|
||||
|
||||
iter++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
QuestInterface *QuestParserCollection::GetQIBySpellQuest(uint32 spell_id) {
|
||||
//first look for /quests/spells/spell_id.ext (precedence)
|
||||
std::string filename = "quests/spells/";
|
||||
filename += itoa(spell_id);
|
||||
std::string tmp;
|
||||
FILE *f = NULL;
|
||||
|
||||
std::list<QuestInterface*>::iterator iter = _load_precedence.begin();
|
||||
while(iter != _load_precedence.end()) {
|
||||
tmp = filename;
|
||||
std::map<uint32, std::string>::iterator ext = _extensions.find((*iter)->GetIdentifier());
|
||||
tmp += ".";
|
||||
tmp += ext->second;
|
||||
f = fopen(tmp.c_str(), "r");
|
||||
if(f) {
|
||||
fclose(f);
|
||||
return (*iter);
|
||||
}
|
||||
|
||||
iter++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
QuestInterface *QuestParserCollection::GetQIByItemQuest(std::string item_script) {
|
||||
//first look for /quests/items/item_script.ext (precedence)
|
||||
std::string filename = "quests/items/";
|
||||
filename += item_script;
|
||||
std::string tmp;
|
||||
FILE *f = NULL;
|
||||
|
||||
std::list<QuestInterface*>::iterator iter = _load_precedence.begin();
|
||||
while(iter != _load_precedence.end()) {
|
||||
tmp = filename;
|
||||
std::map<uint32, std::string>::iterator ext = _extensions.find((*iter)->GetIdentifier());
|
||||
tmp += ".";
|
||||
tmp += ext->second;
|
||||
f = fopen(tmp.c_str(), "r");
|
||||
if(f) {
|
||||
fclose(f);
|
||||
return (*iter);
|
||||
}
|
||||
|
||||
iter++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
#ifndef _EQE_QUESTPARSERCOLLECTION_H
|
||||
#define _EQE_QUESTPARSERCOLLECTION_H
|
||||
|
||||
#include "../common/types.h"
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#include "masterentity.h"
|
||||
#include "../common/Item.h"
|
||||
#include "QuestInterface.h"
|
||||
|
||||
#define QuestFailedToLoad 0xFFFFFFFF
|
||||
#define QuestUnloaded 0x00
|
||||
|
||||
class QuestParserCollection {
|
||||
public:
|
||||
QuestParserCollection();
|
||||
~QuestParserCollection();
|
||||
|
||||
void RegisterQuestInterface(QuestInterface *qi, std::string ext);
|
||||
|
||||
void AddVar(std::string name, std::string val);
|
||||
void ReloadQuests(bool reset_timers = true);
|
||||
|
||||
bool HasQuestSub(uint32 npcid, const char *subname);
|
||||
bool PlayerHasQuestSub(const char *subname);
|
||||
bool SpellHasQuestSub(uint32 spell_id, const char *subname);
|
||||
bool ItemHasQuestSub(ItemInst *itm, const char *subname);
|
||||
|
||||
void EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data);
|
||||
void EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data);
|
||||
void EventItem(QuestEventID evt, Client *client, ItemInst *item, uint32 objid, uint32 extra_data);
|
||||
void EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data);
|
||||
|
||||
private:
|
||||
QuestInterface *GetQIByNPCQuest(uint32 npcid);
|
||||
QuestInterface *GetQIByGlobalNPCQuest();
|
||||
QuestInterface *GetQIByPlayerQuest();
|
||||
QuestInterface *GetQIByGlobalPlayerQuest();
|
||||
QuestInterface *GetQIBySpellQuest(uint32 spell_id);
|
||||
QuestInterface *GetQIByItemQuest(std::string item_script);
|
||||
|
||||
std::map<uint32, QuestInterface*> _interfaces;
|
||||
std::map<uint32, std::string> _extensions;
|
||||
std::list<QuestInterface*> _load_precedence;
|
||||
|
||||
//0x00 = Unloaded
|
||||
//0xFFFFFFFF = Failed to Load
|
||||
std::map<uint32, uint32> _npc_quest_status;
|
||||
uint32 _global_npc_quest_status;
|
||||
uint32 _player_quest_status;
|
||||
uint32 _global_player_quest_status;
|
||||
std::map<uint32, uint32> _spell_quest_status;
|
||||
std::map<std::string, uint32> _item_quest_status;
|
||||
};
|
||||
|
||||
extern QuestParserCollection *parse;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,334 @@
|
||||
#ifndef STRING_IDS
|
||||
#define STRING_IDS
|
||||
|
||||
//These strings are loaded from eqstr_us.txt, but may vary between client versions. Maybe we could make this an enum that's dependent on the client version?
|
||||
#define GENERIC_9_STRINGS 1 //%1 %2 %3 %4 %5 %6 %7 %8 %9
|
||||
#define TARGET_OUT_OF_RANGE 100 //Your target is out of range, get closer!
|
||||
#define TARGET_NOT_FOUND 101 //Target player not found.
|
||||
#define CANNOT_BIND 105 //You cannot form an affinity with this area. Try a city.
|
||||
#define SPELL_DOES_NOT_WORK_HERE 106 //This spell does not work here.
|
||||
#define SPELL_DOES_NOT_WORK_PLANE 107 //This spell does not work on this plane.
|
||||
#define CANT_SEE_TARGET 108 //You cannot see your target.
|
||||
#define MGB_STRING 113 //The next group buff you cast will hit all targets in range.
|
||||
#define TARGET_TOO_FAR 124 //Your target is too far away, get closer!
|
||||
#define PROC_TOOLOW 126 //Your will is not sufficient to command this weapon.
|
||||
#define PROC_PETTOOLOW 127 //Your pet's will is not sufficient to command its weapon.
|
||||
#define DOORS_LOCKED 130 //It's locked and you're not holding the key.
|
||||
#define DOORS_CANT_PICK 131 //This lock cannot be picked.
|
||||
#define DOORS_INSUFFICIENT_SKILL 132 //You are not sufficiently skilled to pick this lock.
|
||||
#define DOORS_GM 133 //You opened the locked door with your magic GM key.
|
||||
#define ITEMS_INSUFFICIENT_LEVEL 136 //You are not sufficient level to use this item.
|
||||
#define GAIN_XP 138 //You gain experience!!
|
||||
#define GAIN_GROUPXP 139 //You gain party experience!!
|
||||
#define BOW_DOUBLE_DAMAGE 143 //Your bow shot did double dmg.
|
||||
#define FORAGE_GRUBS 150 //You have scrounged up some fishing grubs.
|
||||
#define FORAGE_WATER 151 //You have scrounged up some water.
|
||||
#define FORAGE_FOOD 152 //You have scrounged up some food.
|
||||
#define FORAGE_DRINK 153 //You have scrounged up some drink.
|
||||
#define FORAGE_NOEAT 154 //You have scrounged up something that doesn't look edible.
|
||||
#define FORAGE_FAILED 155 //You fail to locate any food nearby.
|
||||
#define ALREADY_FISHING 156 //You are already fishing!
|
||||
#define FISHING_NO_POLE 160 //You can't fish without a fishing pole, go buy one.
|
||||
#define FISHING_EQUIP_POLE 161 //You need to put your fishing pole in your primary hand.
|
||||
#define FISHING_NO_BAIT 162 //You can't fish without fishing bait, go buy some.
|
||||
#define FISHING_CAST 163 //You cast your line.
|
||||
#define NOT_SCARING 164 //You're not scaring anyone.
|
||||
#define FISHING_STOP 165 //You stop fishing and go on your way.
|
||||
#define FISHING_LAND 166 //Trying to catch land sharks perhaps?
|
||||
#define FISHING_LAVA 167 //Trying to catch a fire elemental or something?
|
||||
#define FISHING_FAILED 168 //You didn't catch anything.
|
||||
#define FISHING_POLE_BROKE 169 //Your fishing pole broke!
|
||||
#define FISHING_SUCCESS 170 //You caught, something...
|
||||
#define FISHING_SPILL_BEER 171 //You spill your beer while bringing in your line.
|
||||
#define FISHING_LOST_BAIT 172 //You lost your bait!
|
||||
#define SPELL_FIZZLE 173 //Your spell fizzles!
|
||||
#define MUST_EQUIP_ITEM 179 //You cannot use this item unless it is equipped.
|
||||
#define MISS_NOTE 180 //You miss a note, bringing your song to a close!
|
||||
#define CANNOT_USE_ITEM 181 //Your race, class, or deity cannot use this item.
|
||||
#define ITEM_OUT_OF_CHARGES 182 //Item is out of charges.
|
||||
#define TARGET_NO_MANA 191 //Your target has no mana to affect
|
||||
#define TARGET_GROUP_MEMBER 196 //You must first target a group member.
|
||||
#define INSUFFICIENT_MANA 199 //Insufficient Mana to cast this spell!
|
||||
#define SAC_TOO_LOW 203 //This being is not a worthy sacrifice.
|
||||
#define SAC_TOO_HIGH 204 //This being is too powerful to be a sacrifice.
|
||||
#define CANNOT_SAC_SELF 205 //You cannot sacrifice yourself.
|
||||
#define SILENCED_STRING 207 //You *CANNOT* cast spells, you have been silenced!
|
||||
#define CANNOT_AFFECT_PC 210 //That spell can not affect this target PC.
|
||||
#define SPELL_NEED_TAR 214 //You must first select a target for this spell!
|
||||
#define ONLY_ON_CORPSES 221 //This spell only works on corpses.
|
||||
#define CANT_DRAIN_SELF 224 //You can't drain yourself!
|
||||
#define CORPSE_NOT_VALID 230 //This corpse is not valid.
|
||||
#define CORPSE_TOO_OLD 231 //This player cannot be resurrected. The corpse is too old.
|
||||
#define CAST_OUTDOORS 234 //You can only cast this spell in the outdoors.
|
||||
#define SPELL_RECAST 236 //Spell recast time not yet met.
|
||||
#define SPELL_RECOVERY 237 //Spell recovery time not yet met.
|
||||
#define CANNOT_MEZ 239 //Your target cannot be mesmerized.
|
||||
#define CANNOT_MEZ_WITH_SPELL 240 //Your target cannot be mesmerized (with this spell).
|
||||
#define IMMUNE_STUN 241 //Your target is immune to the stun portion of this effect.
|
||||
#define IMMUNE_ATKSPEED 242 //Your target is immune to changes in its attack speed.
|
||||
#define IMMUNE_FEAR 243 //Your target is immune to fear spells.
|
||||
#define IMMUNE_MOVEMENT 244 //Your target is immune to changes in its run speed.
|
||||
#define ONLY_ONE_PET 246 //You cannot have more than one pet at a time.
|
||||
#define CANNOT_CHARM_YET 248 //Your target is too high of a level for your charm spell.
|
||||
#define CANNOT_AFFECT_NPC 251 //That spell can not affect this target NPC.
|
||||
#define SUSPEND_MINION_HAS_AGGRO 256 //Your pet is the focus of something's attention.
|
||||
#define NO_PET 255 //You do not have a pet.
|
||||
#define CORPSE_CANT_SENSE 262 //You cannot sense any corpses for this PC in this zone.
|
||||
#define SPELL_NO_HOLD 263 //Your spell did not take hold.
|
||||
#define CANNOT_CHARM 267 //This NPC cannot be charmed.
|
||||
#define SPELL_NO_EFFECT 268 //Your target looks unaffected.
|
||||
#define NO_INSTRUMENT_SKILL 269 //Stick to singing until you learn to play this instrument.
|
||||
#define REGAIN_AND_CONTINUE 270 //You regain your concentration and continue your casting.
|
||||
#define SPELL_WOULDNT_HOLD 271 //Your spell would not have taken hold on your target.
|
||||
#define MISSING_SPELL_COMP 272 //You are missing some required spell components.
|
||||
#define INVIS_BEGIN_BREAK 275 //You feel yourself starting to appear.
|
||||
#define DISCIPLINE_CONLOST 278 //You lose the concentration to remain in your fighting discipline.
|
||||
#define REZ_REGAIN 289 //You regain some experience from resurrection.
|
||||
#define DUP_LORE 290 //Duplicate lore items are not allowed.
|
||||
#define TGB_ON 293 //Target other group buff is *ON*.
|
||||
#define TGB_OFF 294 //Target other group buff is *OFF*.
|
||||
#define LDON_SENSE_TRAP1 306 //You do not Sense any traps.
|
||||
#define TRADESKILL_NOCOMBINE 334 //You cannot combine these items in this container type!
|
||||
#define TRADESKILL_FAILED 336 //You lacked the skills to fashion the items together.
|
||||
#define TRADESKILL_TRIVIAL 338 //You can no longer advance your skill from making this item.
|
||||
#define TRADESKILL_SUCCEED 339 //You have fashioned the items together to create something new!
|
||||
#define MEND_CRITICAL 349 //You magically mend your wounds and heal considerable damage.
|
||||
#define MEND_SUCCESS 350 //You mend your wounds and heal some damage.
|
||||
#define MEND_WORSEN 351 //You have worsened your wounds!
|
||||
#define MEND_FAIL 352 //You have failed to mend your wounds.
|
||||
#define LDON_SENSE_TRAP2 367 //You have not detected any traps.
|
||||
#define LOOT_LORE_ERROR 371 //You cannot loot this Lore Item. You already have one.
|
||||
#define PICK_LORE 379 //You cannot pick up a lore item you already possess.
|
||||
#define CONSENT_DENIED 390 //You do not have consent to summon that corpse.
|
||||
#define DISCIPLINE_RDY 393 //You are ready to use a new discipline now.
|
||||
#define CONSENT_INVALID_NAME 397 //Not a valid consent name.
|
||||
#define CONSENT_NPC 398 //You cannot consent NPC\'s.
|
||||
#define CONSENT_YOURSELF 399 //You cannot consent yourself.
|
||||
#define SONG_NEEDS_DRUM 405 //You need to play a percussion instrument for this song
|
||||
#define SONG_NEEDS_WIND 406 //You need to play a wind instrument for this song
|
||||
#define SONG_NEEDS_STRINGS 407 //You need to play a stringed instrument for this song
|
||||
#define SONG_NEEDS_BRASS 408 //You need to play a brass instrument for this song
|
||||
#define AA_GAIN_ABILITY 410 //You have gained the ability "%T1" at a cost of %2 ability %T3.
|
||||
#define AA_IMPROVE 411 //You have improved %T1 %2 at a cost of %3 ability %T4.
|
||||
#define AA_REUSE_MSG 413 //You can use the ability %B1(1) again in %2 hour(s) %3 minute(s) %4 seconds.
|
||||
#define AA_REUSE_MSG2 414 //You can use the ability %B1(1) again in %2 minute(s) %3 seconds.
|
||||
#define YOU_HEALED 419 //%1 has healed you for %2 points of damage.
|
||||
#define BEGINS_TO_GLOW 422 //Your %1 begins to glow.
|
||||
#define ALREADY_INVIS 423 //%1 tries to cast an invisibility spell on you, but you are already invisible.
|
||||
#define YOU_ARE_PROTECTED 424 //%1 tries to cast a spell on you, but you are protected.
|
||||
#define TARGET_RESISTED 425 //Your target resisted the %1 spell.
|
||||
#define YOU_RESIST 426 //You resist the %1 spell!
|
||||
#define SUMMONING_CORPSE 429 //Summoning your corpse.
|
||||
#define SUMMONING_CORPSE_OTHER 430 //Summoning %1's corpse.
|
||||
#define MISSING_SPELL_COMP_ITEM 433 //You are missing %1.
|
||||
#define OTHER_HIT_NONMELEE 434 //%1 was hit by non-melee for %2 points of damage.
|
||||
#define SPELL_WORN_OFF_OF 436 //Your %1 spell has worn off of %2.
|
||||
#define SPELL_WORN_OFF 437 //Your %1 spell has worn off.
|
||||
#define INTERRUPT_SPELL 439 //Your spell is interrupted.
|
||||
#define LOSE_LEVEL 442 //You LOST a level! You are now level %1!
|
||||
#define GAIN_ABILITY_POINT 446 //You have gained an ability point! You now have %1 ability point%2.
|
||||
#define GAIN_LEVEL 447 //You have gained a level! Welcome to level %1!
|
||||
#define LANG_SKILL_IMPROVED 449 //Your language skills have improved.
|
||||
#define OTHER_LOOTED_MESSAGE 466 //--%1 has looted a %2--
|
||||
#define LOOTED_MESSAGE 467 //--You have looted a %1--
|
||||
#define FACTION_WORST 469 //Your faction standing with %1 could not possibly get any worse.
|
||||
#define FACTION_WORSE 470 //Your faction standing with %1 got worse.
|
||||
#define FACTION_BEST 471 //Your faction standing with %1 could not possibly get any better.
|
||||
#define FACTION_BETTER 472 //Your faction standing with %1 got better.
|
||||
#define PET_REPORT_HP 488 //I have %1 percent of my hit points left.
|
||||
#define CORPSE_DECAY1 495 //This corpse will decay in %1 minute(s) %2 seconds.
|
||||
#define DISC_LEVEL_ERROR 503 //You must be a level %1 ... to use this discipline.
|
||||
#define DISCIPLINE_CANUSEIN 504 //You can use a new discipline in %1 minutes %2 seconds.
|
||||
#define PVP_ON 552 //You are now player kill and follow the ways of Discord.
|
||||
#define GENERIC_STRINGID_SAY 554 //%1 says '%T2'
|
||||
#define CANNOT_WAKE 555 //%1 tells you, 'I am unable to wake %2, master.'
|
||||
#define GUILD_NAME_IN_USE 711 //You cannot create a guild with that name, that guild already exists on this server.
|
||||
#define GM_GAINXP 1002 //[GM] You have gained %1 AXP and %2 EXP (%3).
|
||||
#define FINISHING_BLOW 1009 //%1 scores a Finishing Blow!!
|
||||
#define ASSASSINATES 1016 //%1 ASSASSINATES their victim!!
|
||||
#define CRIPPLING_BLOW 1021 //%1 lands a Crippling Blow!(%2)
|
||||
#define CRITICAL_HIT 1023 //%1 scores a critical hit! (%2)
|
||||
#define RESISTS_URGE 1025 //%1 resists their urge to flee.
|
||||
#define BERSERK_START 1027 //%1 goes into a berserker frenzy!
|
||||
#define DEATH_PACT 1028 //%1's death pact has been benevolently fulfilled!
|
||||
#define DIVINE_INTERVENTION 1029 //%1 has been rescued by divine intervention!
|
||||
#define BERSERK_END 1030 //%1 is no longer berserk.
|
||||
#define GATES 1031 //%1 Gates.
|
||||
#define GENERIC_SAY 1032 //%1 says '%2'
|
||||
#define OTHER_REGAIN_CAST 1033 //%1 regains concentration and continues casting.
|
||||
#define GENERIC_SHOUT 1034 //%1 shouts '%2'
|
||||
#define GENERIC_EMOTE 1036 //%1 %2
|
||||
#define NPC_ENRAGE_START 1042 //%1 has become ENRAGED.
|
||||
#define NPC_ENRAGE_END 1043 //%1 is no longer enraged.
|
||||
#define NPC_RAMPAGE 1044 //%1 goes on a RAMPAGE!
|
||||
#define NPC_FLURRY 1045 //%1 executes a FLURRY of attacks on %2!
|
||||
#define DISCIPLINE_FEARLESS 1076 //%1 becomes fearless.
|
||||
#define DUEL_FINISHED 1088 //dont know text
|
||||
#define EATING_MESSAGE 1091 //Chomp, chomp, chomp... %1 takes a bite from a %2.
|
||||
#define DRINKING_MESSAGE 1093 //Glug, glug, glug... %1 takes a drink from a %2.
|
||||
#define SUCCESSFUL_TAUNT 1095 //I'll teach you to interfere with me %3.
|
||||
#define PET_SIT_STRING 1130 //Changing position, Master.
|
||||
#define PET_CALMING 1131 //Sorry, Master..calming down.
|
||||
#define PET_FOLLOWING 1132 //Following you, Master.
|
||||
#define PET_GUARDME_STRING 1133 //Guarding you, Master.
|
||||
#define PET_GUARDINGLIFE 1134 //Guarding with my life..oh splendid one.
|
||||
#define PET_GETLOST_STRING 1135 //As you wish, oh great one.
|
||||
#define PET_LEADERIS 1136 //My leader is %3.
|
||||
#define I_FOLLOW_NOONE 1137 //I follow no one.
|
||||
#define MERCHANT_BUSY 1143 //I'm sorry, I am busy right now.
|
||||
#define MERCHANT_GREETING 1144 //Welcome to my shop, %3.
|
||||
#define MERCHANT_HANDY_ITEM1 1145 //Hello there, %3. How about a nice %4?
|
||||
#define MERCHANT_HANDY_ITEM2 1146 //Greetings, %3. You look like you could use a %4.
|
||||
#define MERCHANT_HANDY_ITEM3 1147 //Hi there %3, just browsing? Have you seen the %4 I just got in?
|
||||
#define MERCHANT_HANDY_ITEM4 1148 //Welcome to my shop, %3. You would probably find a %4 handy.
|
||||
#define AA_POINT 1197 //point
|
||||
#define AA_POINTS 1215 //points
|
||||
#define SPELL_FIZZLE_OTHER 1218 //%1's spell fizzles!
|
||||
#define MISSED_NOTE_OTHER 1219 //A missed note brings %1's song to a close!
|
||||
#define CORPSE_DECAY_NOW 1227 //This corpse is waiting to expire.
|
||||
#define SURNAME_REJECTED 1374 //Your new surname was rejected. Please try a different name.
|
||||
#define DUEL_DECLINE 1383 //%1 has declined your challenge to duel to the death.
|
||||
#define DUEL_ACCEPTED 1384 //%1 has already accepted a duel with someone else.
|
||||
#define DUEL_CONSIDERING 1385 //%1 is considering a duel with someone else.
|
||||
#define PLAYER_REGAIN 1394 //You have control of yourself again.
|
||||
#define REZZ_ALREADY_PENDING 1379 //You were unable to restore the corpse to life, but you may have success with a later attempt.
|
||||
#define IN_USE 1406 //Someone else is using that. Try again later.
|
||||
#define DUEL_FLED 1408 //%1 has defeated %2 in a duel to the death! %3 has fled like a cowardly dog!
|
||||
#define MEMBER_OF_YOUR_GUILD 1429
|
||||
#define OFFICER_OF_YOUR_GUILD 1430
|
||||
#define LEADER_OF_YOUR_GUILD 1431
|
||||
#define RECEIVED_PLATINUM 1452 //You receive %1 Platinum from %2.
|
||||
#define RECEIVED_GOLD 1453 //You receive %1 Gold from %2.
|
||||
#define RECEIVED_SILVER 1454 //You receive %1 Silver from %2.
|
||||
#define RECEIVED_COPPER 1455 //You receive %1 Copper from %2.
|
||||
#define STRING_FEIGNFAILED 1456 //%1 has fallen to the ground.
|
||||
#define DOORS_SUCCESSFUL_PICK 1457 //You successfully picked the lock.
|
||||
#define PLAYER_CHARMED 1461 //You lose control of yourself!
|
||||
#define TRADER_BUSY 1468 //That Trader is currently with a customer. Please wait until their transaction is finished.
|
||||
#define SENSE_CORPSE_DIRECTION 1563 //You sense a corpse in this direction.
|
||||
#define SUSPEND_MINION_UNSUSPEND 3267 //%1 tells you, 'I live again...'
|
||||
#define SUSPEND_MINION_SUSPEND 3268 //%1 tells you, 'By your command, master.'
|
||||
#define ONLY_SUMMONED_PETS 3269 //3269 This effect only works with summoned pets.
|
||||
#define SUSPEND_MINION_FIGHTING 3270 //Your pet must be at peace, first.
|
||||
#define TRADESKILL_MISSING_ITEM 3455 //You are missing a %1.
|
||||
#define TRADESKILL_MISSING_COMPONENTS 3456 //Sorry, but you don't have everything you need for this recipe in your general inventory.
|
||||
#define TRADESKILL_LEARN_RECIPE 3457 //You have learned the recipe %1!
|
||||
#define CORPSEDRAG_LIMIT 4061 //You are already dragging as much as you can!
|
||||
#define CORPSEDRAG_ALREADY 4062 //You are already dragging %1.
|
||||
#define CORPSEDRAG_SOMEONE_ELSE 4063 //Someone else is dragging %1.
|
||||
#define CORPSEDRAG_BEGIN 4064 //You begin to drag %1.
|
||||
#define CORPSEDRAG_STOPALL 4065 //You stop dragging the corpses.
|
||||
#define CORPSEDRAG_STOP 4066 //You stop dragging the corpse.
|
||||
#define WHOALL_NO_RESULTS 5029 //There are no players in EverQuest that match those who filters.
|
||||
#define PETITION_NO_DELETE 5053 //You do not have a petition in the queue.
|
||||
#define PETITION_DELETED 5054 //Your petition was successfully deleted.
|
||||
#define GAIN_RAIDEXP 5085 //You gained raid experience!
|
||||
#define ADVENTURE_COMPLETE 5147 //You received %1 points for successfully completing the adventure.
|
||||
#define PET_ATTACKING 5501 //%1 tells you, 'Attacking %2 Master.'
|
||||
#define FATAL_BOW_SHOT 5745 //%1 performs a FATAL BOW SHOT!!
|
||||
#define MELEE_SILENCE 5806 //You *CANNOT* use this melee ability, you are suffering from amnesia!
|
||||
#define DISCIPLINE_REUSE_MSG 5807 //You can use the ability %1 again in %2 hour(s) %3 minute(s) %4 seconds.
|
||||
#define DISCIPLINE_REUSE_MSG2 5808 //You can use the ability %1 again in %2 minute(s) %3 seconds.
|
||||
#define FAILED_TAUNT 5811 //You have failed to taunt your target.
|
||||
#define AA_NO_TARGET 5825 //You must first select a target for this ability!
|
||||
#define GUILD_BANK_CANNOT_DEPOSIT 6097 // Cannot deposit this item. Containers must be empty, and only one of each LORE and no NO TRADE or TEMPORARY items may be deposited.
|
||||
#define GUILD_BANK_FULL 6098 // There is no more room in the Guild Bank.
|
||||
#define GUILD_BANK_TRANSFERRED 6100 // '%1' transferred to Guild Bank from Deposits.
|
||||
#define GUILD_BANK_EMPTY_HANDS 6108 // You must empty your hands to withdraw from the Guild Bank.
|
||||
#define GENERIC_STRING 6688 //%1 (used to any basic message)
|
||||
#define SENTINEL_TRIG_YOU 6724 //You have triggered your sentinel.
|
||||
#define SENTINEL_TRIG_OTHER 6725 //%1 has triggered your sentinel.
|
||||
#define IDENTIFY_SPELL 6765 //Item Lore: %1.
|
||||
#define LDON_DONT_KNOW_TRAPPED 7552 //You do not know if this object is trapped.
|
||||
#define LDON_HAVE_DISARMED 7553 //You have disarmed %1!
|
||||
#define LDON_ACCIDENT_SETOFF 7554 //You accidentally set off the trap!
|
||||
#define LDON_HAVE_NOT_DISARMED 7555 //You have not disarmed %1.
|
||||
#define LDON_ACCIDENT_SETOFF2 7556 //You accidentally set off the trap!
|
||||
#define LDON_CERTAIN_TRAP 7557 //You are certain that %1 is trapped.
|
||||
#define LDON_CERTAIN_NOT_TRAP 7558 //You are certain that %1 is not trapped.
|
||||
#define LDON_CANT_DETERMINE_TRAP 7559 //You are unable to determine if %1 is trapped.
|
||||
#define LDON_PICKLOCK_SUCCESS 7560 //You have successfully picked %1!
|
||||
#define LDON_PICKLOCK_FAILURE 7561 //You have failed to pick %1.
|
||||
#define LDON_STILL_LOCKED 7562 //You cannot open %1, it is locked.
|
||||
#define LDON_BASH_CHEST 7563 //%1 try to %2 %3, but do no damage.
|
||||
#define DOORS_NO_PICK 7564 //You must have a lock pick in your inventory to do this.
|
||||
#define LDON_NO_LOCKPICK 7564 //You must have a lock pick in your inventory to do this.
|
||||
#define LDON_WAS_NOT_LOCKED 7565 //%1 was not locked.
|
||||
#define LDON_WAS_NOT_TRAPPED 7566 //%1 was not trapped
|
||||
#define GAIN_GROUP_LEADERSHIP_POINT 8585 //
|
||||
#define GAIN_RAID_LEADERSHIP_POINT 8589 //
|
||||
#define MAX_GROUP_LEADERSHIP_POINTS 8584 //
|
||||
#define MAX_RAID_LEADERSHIP_POINTS 8591 //
|
||||
#define LEADERSHIP_EXP_ON 8653 //
|
||||
#define LEADERSHIP_EXP_OFF 8654 //
|
||||
#define CURRENT_SPELL_EFFECTS 8757 //%1's current spell effects:
|
||||
#define GAIN_GROUP_LEADERSHIP_EXP 8788 //
|
||||
#define GAIN_RAID_LEADERSHIP_EXP 8789 //
|
||||
#define BUFF_MINUTES_REMAINING 8799 //%1 (%2 minutes remaining)
|
||||
#define YOU_HEAL 9068 //You have healed %1 for %2 points of damage.
|
||||
#define OTHER_HIT_DOT 9072 //%1 has taken %2 damage from your %3.
|
||||
#define HIT_NON_MELEE 9073 //%1 hit %2 for %3 points of non-melee damage.
|
||||
#define SHAKE_OFF_STUN 9077
|
||||
#define STRIKETHROUGH_STRING 9078 //You strike through your opponent's defenses!
|
||||
#define SPELL_REFLECT 9082 //%1's spell has been reflected by %2.
|
||||
#define NEW_SPELLS_AVAIL 9149 //You have new spells available to you. Check the merchants near your guild master.
|
||||
#define AE_RAMPAGE 11015 //%1 goes on a WILD RAMPAGE!
|
||||
#define FACE_ACCEPTED 12028 //Facial features accepted.
|
||||
#define SPELL_LEVEL_TO_LOW 12048 //You will have to achieve level %1 before you can scribe the %2.
|
||||
#define ATTACKFAILED 12158 //%1 try to %2 %3, but %4!
|
||||
#define HIT_STRING 12183 //hit
|
||||
#define CRUSH_STRING 12191 //crush
|
||||
#define PIERCE_STRING 12193 //pierce
|
||||
#define KICK_STRING 12195 //kick
|
||||
#define STRIKE_STRING 12197 //strike
|
||||
#define BACKSTAB_STRING 12199 //backstab
|
||||
#define BASH_STRING 12201 //bash
|
||||
#define GUILD_NOT_MEMBER 12242 //You are not a member of any guild.
|
||||
#define MEMBER_OF_X_GUILD 12256
|
||||
#define OFFICER_OF_X_GUILD 12257
|
||||
#define LEADER_OF_X_GUILD 12258
|
||||
#define NOT_IN_A_GUILD 12259
|
||||
#define TARGET_PLAYER_FOR_GUILD_STATUS 12260
|
||||
#define GROUP_INVITEE_NOT_FOUND 12268 //You must target a player or use /invite <name> to invite someone to your group.
|
||||
#define GROUP_INVITEE_SELF 12270 //12270 You cannot invite yourself.
|
||||
#define NOT_IN_CONTROL 12368 //You do not have control of yourself right now.
|
||||
#define ALREADY_CASTING 12442 //You are already casting a spell!
|
||||
#define SENSE_CORPSE_NOT_NAME 12446 //You don't sense any corpses of that name.
|
||||
#define SENSE_CORPSE_NONE 12447 //You don't sense any corpses.
|
||||
#define NOT_HOLDING_ITEM 12452 //You are not holding an item!
|
||||
#define SENSE_UNDEAD 12471 //You sense undead in this direction.
|
||||
#define SENSE_ANIMAL 12472 //You sense an animal in this direction.
|
||||
#define SENSE_SUMMONED 12473 //You sense a summoned being in this direction.
|
||||
#define SENSE_NOTHING 12474 //You don't sense anything.
|
||||
#define LDON_SENSE_TRAP3 12476 //You don't sense any traps.
|
||||
#define INTERRUPT_SPELL_OTHER 12478 //%1's casting is interrupted!
|
||||
#define YOU_HIT_NONMELEE 12481 //You were hit by non-melee for %1 damage.
|
||||
#define TRACK_LOST_TARGET 12681 //You have lost your tracking target.
|
||||
#define TRACK_STRAIGHT_AHEAD 12676
|
||||
#define TRACK_AHEAD_AND_TO 12677
|
||||
#define TRACK_TO_THE 12678
|
||||
#define TRACK_BEHIND_AND_TO 12679
|
||||
#define TRACK_BEHIND_YOU 12680
|
||||
#define BEAM_SMILE 12501 //%1 beams a smile at %2
|
||||
#define SONG_ENDS_ABRUPTLY 12686 //Your song ends abruptly.
|
||||
#define SONG_ENDS 12687 //Your song ends.
|
||||
#define SONG_ENDS_OTHER 12688 //%1's song ends.
|
||||
#define SONG_ENDS_ABRUPTLY_OTHER 12689 //%1's song ends abruptly.
|
||||
#define DIVINE_AURA_NO_ATK 12695 //You can't attack while invulnerable!
|
||||
#define TRY_ATTACKING_SOMEONE 12696 //Try attacking someone other than yourself, it's more productive.
|
||||
#define BACKSTAB_WEAPON 12874 //You need a piercing weapon as your primary weapon in order to backstab
|
||||
#define MORE_SKILLED_THAN_I 12931 //%1 tells you, 'You are more skilled than I! What could I possibly teach you?'
|
||||
#define SURNAME_EXISTS 12939 //You already have a surname. Operation failed.
|
||||
#define SURNAME_LEVEL 12940 //You can only submit a surname upon reaching the 20th level. Operation failed.
|
||||
#define SURNAME_TOO_LONG 12942 //Surname must be less than 20 characters in length.
|
||||
#define REPORT_ONCE 12945 //You may only submit a report once per time that you zone. Thank you.
|
||||
#define NOW_INVISIBLE 12950 //%1 is now Invisible.
|
||||
#define NOW_VISIBLE 12951 //%1 is now Visible.
|
||||
#define GUILD_NOT_MEMBER2 12966 //You are not in a guild.
|
||||
#define DISC_LEVEL_USE_ERROR 13004 //You are not sufficient level to use this discipline.
|
||||
#define TOGGLE_ON 13172 //Asking server to turn ON your incoming tells.
|
||||
#define TOGGLE_OFF 13173 //Asking server to turn OFF all incoming tells for you.
|
||||
#define DUEL_INPROGRESS 13251 //You have already accepted a duel with someone else cowardly dog.
|
||||
#define GENERIC_MISS 15041 //%1 missed %2
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "../common/debug.h"
|
||||
#include "ZoneConfig.h"
|
||||
|
||||
ZoneConfig *ZoneConfig::_zone_config = NULL;
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef __ZoneConfig_H
|
||||
#define __ZoneConfig_H
|
||||
|
||||
#include "../common/EQEmuConfig.h"
|
||||
|
||||
class ZoneConfig : public EQEmuConfig {
|
||||
public:
|
||||
uint16 ZonePort;
|
||||
string ZoneAddress;
|
||||
|
||||
private:
|
||||
|
||||
static ZoneConfig *_zone_config;
|
||||
|
||||
ZoneConfig() : EQEmuConfig() {
|
||||
ZonePort=0;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// Produce a const singleton
|
||||
static const ZoneConfig *get() {
|
||||
if (_zone_config == NULL)
|
||||
LoadConfig();
|
||||
return(_zone_config);
|
||||
}
|
||||
|
||||
// Load the config
|
||||
static bool LoadConfig() {
|
||||
if (_zone_config != NULL)
|
||||
delete _zone_config;
|
||||
_zone_config=new ZoneConfig;
|
||||
_config=_zone_config;
|
||||
|
||||
return _config->ParseFile(EQEmuConfig::ConfigFile.c_str(),"server");
|
||||
}
|
||||
|
||||
// Accessors for the static private object
|
||||
static void SetZonePort(uint16 port) { if (_zone_config) _zone_config->ZonePort=port; }
|
||||
|
||||
void Dump() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
+1480
File diff suppressed because it is too large
Load Diff
+4334
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,178 @@
|
||||
const char *notin = "~.? ,)=!&|<>\"";
|
||||
|
||||
const char * charIn = "`~1234567890-=!@#$%^&*()_+qwertyuiop[]asdfghjkl;'zxcvbnm,./QWERTYUIOP|ASDFGHJKL:ZXCVBNM<>?\"{}";
|
||||
const char * charIn2 = "`~1234567890-=!@#$%^&*()_+qwertyuiop[]asdfghjkl;'zxcvbnm,./QWERTYUIOP|ASDFGHJKL:ZXCVBNM<>?\" ";
|
||||
|
||||
char com_list[512];
|
||||
|
||||
/*char * gettok(const char * string, int chara, int pos) {
|
||||
static char * pch;
|
||||
static char temp[100];
|
||||
static char ty[100];
|
||||
memset(temp, 0, sizeof(temp));
|
||||
memset(ty, 0, sizeof(ty));
|
||||
ty[0] = chara;
|
||||
strn0cpy(temp, string, sizeof(temp));
|
||||
pch = strtok(temp,ty);
|
||||
for (int i=0; i < pos; i++) {
|
||||
if (pos == i) break;
|
||||
pch = strtok(NULL,ty);
|
||||
}
|
||||
return pch;
|
||||
}*/
|
||||
|
||||
|
||||
int calc(char * stuff) {
|
||||
int result = 0;
|
||||
int i = 0;
|
||||
int a = 0;
|
||||
static char temp[100];
|
||||
int op = 0;
|
||||
memset(temp,0x0,100);
|
||||
//char heh[100];
|
||||
while(*stuff)
|
||||
{
|
||||
a++;
|
||||
|
||||
if (*stuff >= '0' && *stuff <= '9') {
|
||||
if (op) {
|
||||
switch ( op ) {
|
||||
case 0:
|
||||
break;
|
||||
case '+':
|
||||
result += atoi(stuff);
|
||||
memset(temp,0x0,100);
|
||||
i = 0;
|
||||
break;
|
||||
case '-':
|
||||
result -= atoi(stuff);
|
||||
memset(temp,0x0,100);
|
||||
i = 0;
|
||||
break;
|
||||
case '*':
|
||||
result *= atoi(stuff);
|
||||
memset(temp,0x0,100);
|
||||
i = 0;
|
||||
break;
|
||||
case '/':
|
||||
result /= atoi(stuff);
|
||||
memset(temp,0x0,100);
|
||||
i = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
temp[i] = *stuff;
|
||||
}
|
||||
else if (*stuff == '+' || *stuff == '-' || *stuff == '/' || *stuff == '*') {
|
||||
op = *stuff;
|
||||
if (!result) result = atoi(temp);
|
||||
memset(temp,0x0,100);
|
||||
i=0;
|
||||
}
|
||||
i++;
|
||||
stuff++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
char * postring (char * string, int pos) {
|
||||
static char temp[1024];
|
||||
memset(temp, 0, sizeof(temp));
|
||||
int p=0;
|
||||
int tmpStringLen = strlen(string);
|
||||
for (int i=pos; i < tmpStringLen; i++) {
|
||||
temp[p] = string[i];
|
||||
p++;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
int g_id ( char * string )
|
||||
{
|
||||
char temp[100];
|
||||
int i=0;
|
||||
while (*string)
|
||||
{
|
||||
if (*string >= '0' && *string <= '9') temp[i++] = *string++;
|
||||
else string++;
|
||||
}
|
||||
return atoi(temp);
|
||||
}
|
||||
|
||||
int GetArgs(char * string)
|
||||
{
|
||||
#if 1
|
||||
char temp[255];
|
||||
char c_name[255];
|
||||
int params = 0;
|
||||
//char *buffer = new char[512]; // this is never deleted, causes zone to crash
|
||||
char *buffer = com_list;
|
||||
memset(temp,0x0,255);
|
||||
//memset(buffer,0x0,512);
|
||||
//#ifdef WIN32
|
||||
//strcpy(buffer,com_list);
|
||||
//#else
|
||||
//strncpy(buffer,com_list,sizeof(buffer)-1);
|
||||
//#endif
|
||||
int i=0;
|
||||
while (*buffer)
|
||||
{
|
||||
if (*buffer != '|' && *buffer != ' ') temp[i++] = *buffer++;
|
||||
else buffer++;
|
||||
if (*buffer == '|') {
|
||||
params = atoi(temp);
|
||||
if (!strcmp(c_name,string)) {
|
||||
return params;
|
||||
}
|
||||
memset(temp,0x0,255);
|
||||
i=0;
|
||||
}
|
||||
if (*buffer == ' ') {
|
||||
memset(c_name,0x0,255);
|
||||
strcpy(c_name,temp);
|
||||
memset(temp,0x0,255);
|
||||
i=0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
if (strstr(string,"if")) { return 0; }
|
||||
if (strstr(string,"sfollow")) { return 0; }
|
||||
if (strstr(string,"save")) { return 0; }
|
||||
if (strstr(string,"while")) { return 0; }
|
||||
if (strstr(string,"break")) { return 1; }
|
||||
if (strstr(string,"follow")) { return 1; }
|
||||
if (strstr(string,"setallskill")) { return 1; }
|
||||
if (strstr(string,"me")) { return 1; }
|
||||
if (strstr(string,"flagcheck")) { return 1; }
|
||||
if (strstr(string,"echo")) { return 1; }
|
||||
if (strstr(string,"summonitem")) { return 1; }
|
||||
if (strstr(string,"say")) { return 1; }
|
||||
if (strstr(string,"emote")) { return 1; }
|
||||
if (strstr(string,"shout")) { return 1; }
|
||||
if (strstr(string,"depop")) { return 1; }
|
||||
if (strstr(string,"cumflag")) { return 1; }
|
||||
if (strstr(string,"exp")) { return 1; }
|
||||
if (strstr(string,"level")) { return 1; }
|
||||
if (strstr(string,"safemove")) { return 1; }
|
||||
if (strstr(string,"rain")) { return 1; }
|
||||
if (strstr(string,"snow")) { return 1; }
|
||||
if (strstr(string,"pvp")) { return 1; }
|
||||
if (strstr(string,"doanim")) { return 1; }
|
||||
if (strstr(string,"dbspawnadd")) { return 2; }
|
||||
if (strstr(string,"castspell")) { return 2; }
|
||||
if (strstr(string,"flagcheck")) { return 2; }
|
||||
if (strstr(string,"addskill")) { return 2; }
|
||||
if (strstr(string,"write")) { return 2; }
|
||||
if (strstr(string,"settarget")) { return 2; }
|
||||
if (strstr(string,"givecash")) { return 4; }
|
||||
if (strstr(string,"movepc")) { return 4; }
|
||||
if (strstr(string,"spawn")) { return 6; }
|
||||
return 0;
|
||||
#endif // 0
|
||||
}
|
||||
|
||||
Client* gClient = 0;
|
||||
|
||||
uint32 Line_Number = 0;
|
||||
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
solar: Beacon class, extends Mob. Used for AE rain spells to have a mob
|
||||
target to center around.
|
||||
|
||||
*/
|
||||
|
||||
#include "../common/debug.h"
|
||||
#ifdef _WINDOWS
|
||||
#define snprintf _snprintf
|
||||
#if (_MSC_VER < 1500)
|
||||
#define vsnprintf _vsnprintf
|
||||
#endif
|
||||
#define strncasecmp _strnicmp
|
||||
#define strcasecmp _stricmp
|
||||
#endif
|
||||
|
||||
#include "masterentity.h"
|
||||
#include "spdat.h"
|
||||
|
||||
extern EntityList entity_list;
|
||||
extern Zone* zone;
|
||||
|
||||
// solar: if lifetime is 0 this is a permanent beacon.. not sure if that'll be
|
||||
// useful for anything
|
||||
Beacon::Beacon(Mob *at_mob, int lifetime)
|
||||
:Mob
|
||||
(
|
||||
NULL, NULL, 0, 0, 0, INVISIBLE_MAN, 0, BT_NoTarget, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
),
|
||||
remove_timer(lifetime),
|
||||
spell_timer(0)
|
||||
{
|
||||
remove_timer.Disable();
|
||||
spell_timer.Disable();
|
||||
remove_me = false;
|
||||
spell_id = 0xFFFF;
|
||||
resist_adjust = 0;
|
||||
spell_iterations = 0;
|
||||
caster_id = 0;
|
||||
|
||||
// copy location
|
||||
x_pos = at_mob->GetX();
|
||||
y_pos = at_mob->GetY();
|
||||
z_pos = at_mob->GetZ();
|
||||
heading = at_mob->GetHeading();
|
||||
|
||||
if(lifetime)
|
||||
{
|
||||
remove_timer.Start();
|
||||
}
|
||||
#ifdef SOLAR
|
||||
entity_list.Message(0, 0, "Beacon being created at %0.2f %0.2f %0.2f heading %0.2f lifetime %d", GetX(), GetY(), GetZ(), GetHeading(), lifetime);
|
||||
#endif
|
||||
}
|
||||
|
||||
Beacon::~Beacon()
|
||||
{
|
||||
#ifdef SOLAR
|
||||
entity_list.Message(0, 0, "Beacon %d being removed at %0.2f %0.2f %0.2f heading %0.2f", GetID(), GetX(), GetY(), GetZ(), GetHeading());
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Beacon::Process()
|
||||
{
|
||||
if(remove_me)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if
|
||||
(
|
||||
spell_timer.Enabled() &&
|
||||
spell_timer.Check() &&
|
||||
IsValidSpell(spell_id)
|
||||
)
|
||||
{
|
||||
Mob *caster = entity_list.GetMob(caster_id);
|
||||
if(caster && spell_iterations--)
|
||||
{
|
||||
bool affect_caster = (!caster->IsNPC() && !caster->IsAIControlled()); //NPC AE spells do not affect the NPC caster
|
||||
entity_list.AESpell(caster, this, spell_id, affect_caster, resist_adjust);
|
||||
}
|
||||
else
|
||||
{
|
||||
// spell is done casting, or caster disappeared
|
||||
spell_id = 0xFFFF;
|
||||
spell_iterations = 0;
|
||||
spell_timer.Disable();
|
||||
caster_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(remove_timer.Enabled() && remove_timer.Check())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Beacon::AELocationSpell(Mob *caster, uint16 cast_spell_id, int16 resist_adjust)
|
||||
{
|
||||
if(!IsValidSpell(cast_spell_id) || !caster)
|
||||
return;
|
||||
|
||||
caster_id = caster->GetID();
|
||||
spell_id = cast_spell_id;
|
||||
this->resist_adjust = resist_adjust;
|
||||
spell_iterations = spells[spell_id].AEDuration / 2500;
|
||||
spell_iterations = spell_iterations < 1 ? 1 : spell_iterations; // at least 1
|
||||
spell_timer.Start(2500);
|
||||
spell_timer.Trigger();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef BEACON_H
|
||||
#define BEACON_H
|
||||
|
||||
#include "entity.h"
|
||||
#include "mob.h"
|
||||
#include "../common/types.h"
|
||||
#include "../common/timer.h"
|
||||
|
||||
class Beacon : public Mob
|
||||
{
|
||||
public:
|
||||
Beacon(Mob *at_mob, int lifetime);
|
||||
~Beacon();
|
||||
|
||||
//abstract virtual function implementations requird by base abstract class
|
||||
virtual void Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillType attack_skill) { return; }
|
||||
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false) { return; }
|
||||
virtual bool Attack(Mob* other, int Hand = 13, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false) { return false; }
|
||||
virtual bool HasRaid() { return false; }
|
||||
virtual bool HasGroup() { return false; }
|
||||
virtual Raid* GetRaid() { return 0; }
|
||||
virtual Group* GetGroup() { return 0; }
|
||||
|
||||
bool IsBeacon() const { return true; }
|
||||
bool Process();
|
||||
virtual void Depop(bool not_used = true) { remove_me = true; }
|
||||
void AELocationSpell(Mob *caster, uint16 cast_spell_id, int16 resist_adjust);
|
||||
|
||||
protected:
|
||||
Timer remove_timer;
|
||||
bool remove_me;
|
||||
|
||||
uint16 spell_id;
|
||||
int16 resist_adjust;
|
||||
int spell_iterations;
|
||||
Timer spell_timer;
|
||||
|
||||
uint16 caster_id;
|
||||
private:
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,9 @@
|
||||
#endif
|
||||
#ifndef Client #include "client.h"
|
||||
#endif
|
||||
#include "Object.h"
|
||||
#include "groups.h"
|
||||
#include "doors.h"
|
||||
|
||||
|
||||
//This file looks important
|
||||
+3475
File diff suppressed because it is too large
Load Diff
+17491
File diff suppressed because it is too large
Load Diff
+691
@@ -0,0 +1,691 @@
|
||||
#ifndef BOT_H
|
||||
#define BOT_H
|
||||
|
||||
#ifdef BOTS
|
||||
|
||||
#include "botStructs.h"
|
||||
#include "mob.h"
|
||||
#include "client.h"
|
||||
#include "pets.h"
|
||||
#include "groups.h"
|
||||
#include "PlayerCorpse.h"
|
||||
#include "zonedb.h"
|
||||
#include "StringIDs.h"
|
||||
#include "../common/MiscFunctions.h"
|
||||
#include "../common/debug.h"
|
||||
#include "guild_mgr.h"
|
||||
#include "worldserver.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
extern bool spells_loaded;
|
||||
extern WorldServer worldserver;
|
||||
|
||||
const int BotAISpellRange = 100; // TODO: Write a method that calcs what the bot's spell range is based on spell, equipment, AA, whatever and replace this
|
||||
const int MaxSpellTimer = 15;
|
||||
const int MaxDisciplineTimer = 10;
|
||||
const int DisciplineReuseStart = MaxSpellTimer + 1;
|
||||
const int MaxTimer = MaxSpellTimer + MaxDisciplineTimer;
|
||||
const int MaxStances = 7;
|
||||
const int MaxSpellTypes = 16;
|
||||
const int MaxHealRotationMembers = 6;
|
||||
const int MaxHealRotationTargets = 3;
|
||||
|
||||
typedef enum BotStanceType {
|
||||
BotStancePassive,
|
||||
BotStanceBalanced,
|
||||
BotStanceEfficient,
|
||||
BotStanceReactive,
|
||||
BotStanceAggressive,
|
||||
BotStanceBurn,
|
||||
BotStanceBurnAE
|
||||
};
|
||||
|
||||
typedef enum SpellTypeIndex {
|
||||
SpellType_NukeIndex,
|
||||
SpellType_HealIndex,
|
||||
SpellType_RootIndex,
|
||||
SpellType_BuffIndex,
|
||||
SpellType_EscapeIndex,
|
||||
SpellType_PetIndex,
|
||||
SpellType_LifetapIndex,
|
||||
SpellType_SnareIndex,
|
||||
SpellType_DOTIndex,
|
||||
SpellType_DispelIndex,
|
||||
SpellType_InCombatBuffIndex,
|
||||
SpellType_MezIndex,
|
||||
SpellType_CharmIndex,
|
||||
SpellType_SlowIndex,
|
||||
SpellType_DebuffIndex,
|
||||
SpellType_CureIndex
|
||||
};
|
||||
|
||||
class Bot : public NPC {
|
||||
public:
|
||||
// Class enums
|
||||
typedef enum BotfocusType { //focus types
|
||||
BotfocusSpellHaste = 1,
|
||||
BotfocusSpellDuration,
|
||||
BotfocusRange,
|
||||
BotfocusReagentCost,
|
||||
BotfocusManaCost,
|
||||
BotfocusImprovedHeal,
|
||||
BotfocusImprovedDamage,
|
||||
BotfocusImprovedDOT, //i dont know about this...
|
||||
BotfocusImprovedDamage2,
|
||||
BotfocusImprovedUndeadDamage,
|
||||
BotfocusPetPower,
|
||||
BotfocusResistRate,
|
||||
BotfocusSpellHateMod,
|
||||
BotfocusTriggerOnCast,
|
||||
BotfocusSpellVulnerability,
|
||||
BotfocusTwincast,
|
||||
BotfocusSympatheticProc,
|
||||
BotfocusSpellDamage,
|
||||
BotfocusFF_Damage_Amount,
|
||||
BotfocusSpellDurByTic,
|
||||
BotfocusSwarmPetDuration,
|
||||
BotfocusReduceRecastTime,
|
||||
BotfocusBlockNextSpell,
|
||||
BotfocusHealRate,
|
||||
BotfocusAdditionalDamage,
|
||||
BotfocusSpellEffectiveness,
|
||||
BotfocusIncreaseNumHits,
|
||||
BotfocusCriticalHealRate,
|
||||
BotfocusAdditionalHeal2,
|
||||
BotfocusAdditionalHeal,
|
||||
};
|
||||
|
||||
typedef enum BotTradeType { // types of trades a bot can do
|
||||
BotTradeClientNormal,
|
||||
BotTradeClientNoDropNoTrade
|
||||
};
|
||||
|
||||
typedef enum BotRoleType {
|
||||
BotRoleMainAssist,
|
||||
BotRoleGroupHealer,
|
||||
BotRoleRaidHealer
|
||||
};
|
||||
|
||||
typedef enum EqExpansions {
|
||||
ExpansionNone,
|
||||
ExpansionEQ,
|
||||
ExpansionRoK,
|
||||
ExpansionSoV,
|
||||
ExpansionSoL,
|
||||
ExpansionPoP,
|
||||
ExpansionLoY,
|
||||
ExpansionLDoN,
|
||||
ExpansionGoD,
|
||||
ExpansionOoW,
|
||||
ExpansionDoN,
|
||||
ExpansionDoDH,
|
||||
ExpansionPoR,
|
||||
ExpansionTSS,
|
||||
ExpansionSoF,
|
||||
ExpansionSoD,
|
||||
ExpansionUF,
|
||||
ExpansionHoT,
|
||||
ExpansionVoA,
|
||||
ExpansionRoF
|
||||
};
|
||||
|
||||
// Class Constructors
|
||||
Bot(NPCType npcTypeData, Client* botOwner);
|
||||
Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType npcTypeData);
|
||||
|
||||
//abstract virtual function implementations requird by base abstract class
|
||||
virtual void Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillType attack_skill);
|
||||
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false);
|
||||
virtual bool Attack(Mob* other, int Hand = 13, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false);
|
||||
virtual bool HasRaid() { return (GetRaid() ? true : false); }
|
||||
virtual bool HasGroup() { return (GetGroup() ? true : false); }
|
||||
virtual Raid* GetRaid() { return entity_list.GetRaidByMob(this); }
|
||||
virtual Group* GetGroup() { return entity_list.GetGroupByMob(this); }
|
||||
|
||||
// Common, but informal "interfaces" with Client object
|
||||
uint32 CharacterID() { return GetBotID(); } // Just returns the Bot Id
|
||||
inline bool IsInAGuild() const { return (_guildId != GUILD_NONE && _guildId != 0); }
|
||||
inline bool IsInGuild(uint32 in_gid) const { return (in_gid == _guildId && IsInAGuild()); }
|
||||
inline uint32 GuildID() const { return _guildId; }
|
||||
inline uint8 GuildRank() const { return _guildRank; }
|
||||
|
||||
// Class Methods
|
||||
bool IsValidRaceClassCombo();
|
||||
bool IsValidName();
|
||||
bool IsBotNameAvailable(std::string* errorMessage);
|
||||
bool DeleteBot(std::string* errorMessage);
|
||||
void Spawn(Client* botCharacterOwner, std::string* errorMessage);
|
||||
virtual void SetLevel(uint8 in_level, bool command = false);
|
||||
virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
|
||||
virtual bool Process();
|
||||
void FinishTrade(Client* client, BotTradeType tradeType);
|
||||
virtual bool Save();
|
||||
virtual void Depop();
|
||||
void CalcBotStats(bool showtext = true);
|
||||
uint16 BotGetSpells(int spellslot) { return AIspells[spellslot].spellid; }
|
||||
uint16 BotGetSpellType(int spellslot) { return AIspells[spellslot].type; }
|
||||
uint16 BotGetSpellPriority(int spellslot) { return AIspells[spellslot].priority; }
|
||||
virtual float GetProcChances(float &ProcBonus, float &ProcChance, uint16 weapon_speed, uint16 hand);
|
||||
virtual bool AvoidDamage(Mob* other, int32 &damage, bool CanRiposte);
|
||||
virtual int GetMonkHandToHandDamage(void);
|
||||
virtual void TryCriticalHit(Mob *defender, uint16 skill, int32 &damage);
|
||||
virtual bool TryFinishingBlow(Mob *defender, SkillType skillinuse);
|
||||
virtual void DoRiposte(Mob* defender);
|
||||
inline virtual int16 GetATK() const { return ATK + itembonuses.ATK + spellbonuses.ATK + ((GetSTR() + GetSkill(OFFENSE)) * 9 / 10); }
|
||||
inline virtual int16 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; }
|
||||
uint16 GetTotalATK();
|
||||
uint16 GetATKRating();
|
||||
uint16 GetPrimarySkillValue();
|
||||
uint16 MaxSkill(SkillType skillid, uint16 class_, uint16 level) const;
|
||||
inline uint16 MaxSkill(SkillType skillid) const { return MaxSkill(skillid, GetClass(), GetLevel()); }
|
||||
virtual void MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit);
|
||||
virtual void DoSpecialAttackDamage(Mob *who, SkillType skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance=false);
|
||||
virtual void TryBackstab(Mob *other,int ReuseTime = 10);
|
||||
virtual void RogueBackstab(Mob* other, bool min_damage = false, int ReuseTime = 10);
|
||||
virtual void RogueAssassinate(Mob* other);
|
||||
virtual void DoClassAttacks(Mob *target, bool IsRiposte=false);
|
||||
virtual bool TryHeadShot(Mob* defender, SkillType skillInUse);
|
||||
virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillType skillinuse, int16 chance_mod=0, int16 focus=0, bool CanRiposte=false);
|
||||
virtual void ApplySpecialAttackMod(SkillType skill, int32 &dmg, int32 &mindmg);
|
||||
bool CanDoSpecialAttack(Mob *other);
|
||||
virtual int32 CheckAggroAmount(uint16 spellid);
|
||||
virtual void CalcBonuses();
|
||||
void CalcItemBonuses();
|
||||
virtual void MakePet(uint16 spell_id, const char* pettype, const char *petname = NULL);
|
||||
virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther);
|
||||
inline virtual bool IsPet() { return false; }
|
||||
virtual bool IsNPC() const { return false; }
|
||||
virtual Mob* GetOwner();
|
||||
virtual Mob* GetOwnerOrSelf();
|
||||
inline virtual bool HasOwner() { return (GetBotOwner() ? true : false); }
|
||||
virtual int32 CheckHealAggroAmount(uint16 spellid, uint32 heal_possible = 0);
|
||||
virtual int32 CalcMaxMana();
|
||||
virtual void SetAttackTimer();
|
||||
uint32 GetClassHPFactor();
|
||||
virtual int32 CalcMaxHP();
|
||||
bool DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, uint16 slot, bool &stopLogic);
|
||||
bool DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, uint16 slot, bool &stopLogic);
|
||||
bool DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, uint16 slot, bool &stopLogic);
|
||||
void SendBotArcheryWearChange(uint8 material_slot, uint32 material, uint32 color);
|
||||
void Camp(bool databaseSave = true);
|
||||
virtual void AddToHateList(Mob* other, int32 hate = 0, int32 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false);
|
||||
virtual void SetTarget(Mob* mob);
|
||||
virtual void Zone();
|
||||
std::vector<AISpells_Struct> GetBotSpells() { return AIspells; }
|
||||
bool IsArcheryRange(Mob* target);
|
||||
void ChangeBotArcherWeapons(bool isArcher);
|
||||
void Sit();
|
||||
void Stand();
|
||||
bool IsSitting();
|
||||
bool IsStanding();
|
||||
bool IsBotCasterCombatRange(Mob *target);
|
||||
bool CalculateNewPosition2(float x, float y, float z, float speed, bool checkZ = true) ;
|
||||
bool UseDiscipline(uint32 spell_id, uint32 target);
|
||||
uint8 GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets);
|
||||
bool GetNeedsCured(Mob *tar);
|
||||
bool HasOrMayGetAggro();
|
||||
void SetDefaultBotStance();
|
||||
void CalcChanceToCast();
|
||||
void CreateHealRotation( Mob* target, uint32 timer = 10000 );
|
||||
bool AddHealRotationMember( Bot* healer );
|
||||
bool RemoveHealRotationMember( Bot* healer );
|
||||
bool AddHealRotationTarget( Mob* target );
|
||||
//bool AddHealRotationTarget( const char *targetName, int index);
|
||||
bool AddHealRotationTarget( Mob* target, int index);
|
||||
bool RemoveHealRotationTarget( Mob* target );
|
||||
bool RemoveHealRotationTarget( int index);
|
||||
void NotifyNextHealRotationMember( bool notifyNow = false );
|
||||
void ClearHealRotationLeader() { _healRotationLeader = NULL; }
|
||||
void ClearHealRotationMembers();
|
||||
void ClearHealRotationTargets();
|
||||
inline virtual int16 GetMaxStat();
|
||||
inline virtual int16 GetMaxResist();
|
||||
inline virtual int16 GetMaxSTR();
|
||||
inline virtual int16 GetMaxSTA();
|
||||
inline virtual int16 GetMaxDEX();
|
||||
inline virtual int16 GetMaxAGI();
|
||||
inline virtual int16 GetMaxINT();
|
||||
inline virtual int16 GetMaxWIS();
|
||||
inline virtual int16 GetMaxCHA();
|
||||
inline virtual int16 GetMaxMR();
|
||||
inline virtual int16 GetMaxPR();
|
||||
inline virtual int16 GetMaxDR();
|
||||
inline virtual int16 GetMaxCR();
|
||||
inline virtual int16 GetMaxFR();
|
||||
inline virtual int16 GetMaxCorrup();
|
||||
int16 CalcATK();
|
||||
int16 CalcSTR();
|
||||
int16 CalcSTA();
|
||||
int16 CalcDEX();
|
||||
int16 CalcAGI();
|
||||
int16 CalcINT();
|
||||
int16 CalcWIS();
|
||||
int16 CalcCHA();
|
||||
int16 CalcMR();
|
||||
int16 CalcFR();
|
||||
int16 CalcDR();
|
||||
int16 CalcPR();
|
||||
int16 CalcCR();
|
||||
int16 CalcCorrup();
|
||||
int32 CalcHPRegenCap();
|
||||
int32 CalcManaRegenCap();
|
||||
int32 LevelRegen();
|
||||
int32 CalcHPRegen();
|
||||
int32 CalcManaRegen();
|
||||
uint32 CalcCurrentWeight();
|
||||
int GroupLeadershipAAHealthEnhancement();
|
||||
int GroupLeadershipAAManaEnhancement();
|
||||
int GroupLeadershipAAHealthRegeneration();
|
||||
int GroupLeadershipAAOffenseEnhancement();
|
||||
void CalcRestState();
|
||||
int32 CalcMaxEndurance(); //This calculates the maximum endurance we can have
|
||||
int32 CalcBaseEndurance(); //Calculates Base End
|
||||
int32 CalcEnduranceRegen(); //Calculates endurance regen used in DoEnduranceRegen()
|
||||
int32 GetEndurance() const {return cur_end;} //This gets our current endurance
|
||||
int32 GetMaxEndurance() const {return max_end;} //This gets our endurance from the last CalcMaxEndurance() call
|
||||
int32 CalcEnduranceRegenCap();
|
||||
inline uint8 GetEndurancePercent() { return (uint8)((float)cur_end / (float)max_end * 100.0f); }
|
||||
void SetEndurance(int32 newEnd); //This sets the current endurance to the new value
|
||||
void DoEnduranceRegen(); //This Regenerates endurance
|
||||
void DoEnduranceUpkeep(); //does the endurance upkeep
|
||||
|
||||
// AI Methods
|
||||
virtual bool AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes);
|
||||
virtual bool AI_EngagedCastCheck();
|
||||
virtual bool AI_PursueCastCheck();
|
||||
virtual bool AI_IdleCastCheck();
|
||||
bool AIHealRotation(Mob* tar, bool useFastHeals);
|
||||
|
||||
// Mob AI Virtual Override Methods
|
||||
virtual void AI_Process();
|
||||
virtual void AI_Stop();
|
||||
|
||||
// Mob Spell Virtual Override Methods
|
||||
virtual void SpellProcess();
|
||||
int32 Additional_SpellDmg(uint16 spell_id, bool bufftick = false);
|
||||
int32 Additional_Heal(uint16 spell_id);
|
||||
virtual int32 GetActSpellDamage(uint16 spell_id, int32 value);
|
||||
virtual int32 GetActSpellHealing(uint16 spell_id, int32 value);
|
||||
virtual int32 GetActSpellCasttime(uint16 spell_id, int32 casttime);
|
||||
virtual int32 GetActSpellCost(uint16 spell_id, int32 cost);
|
||||
virtual float GetActSpellRange(uint16 spell_id, float range);
|
||||
virtual int32 GetActSpellDuration(uint16 spell_id, int32 duration);
|
||||
virtual float GetAOERange(uint16 spell_id);
|
||||
virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100);
|
||||
virtual void DoBuffTic(uint16 spell_id, uint32 ticsremaining, uint8 caster_level, Mob* caster = 0);
|
||||
virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = 10, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, int16 *resist_adjust = NULL);
|
||||
virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar);
|
||||
virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster);
|
||||
virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction);
|
||||
virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot = 10, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF);
|
||||
|
||||
// Bot Action Command Methods
|
||||
bool MesmerizeTarget(Mob* target);
|
||||
bool Bot_Command_Resist(int resisttype, int level);
|
||||
bool Bot_Command_DireTarget(int diretype, Mob *target);
|
||||
bool Bot_Command_CharmTarget(int charmtype, Mob *target);
|
||||
bool Bot_Command_CalmTarget(Mob *target);
|
||||
bool Bot_Command_RezzTarget(Mob *target);
|
||||
bool Bot_Command_Cure(int curetype, int level);
|
||||
|
||||
// Bot Equipment & Inventory Class Methods
|
||||
void BotTradeSwapItem(Client* client, int16 lootSlot, const ItemInst* inst, const ItemInst* inst_swap, uint32 equipableSlots, std::string* errorMessage, bool swap = true);
|
||||
void BotTradeAddItem(uint32 id, const ItemInst* inst, int16 charges, uint32 equipableSlots, uint16 lootSlot, std::string* errorMessage, bool addToDb = true);
|
||||
void EquipBot(std::string* errorMessage);
|
||||
bool CheckLoreConflict(const Item_Struct* item);
|
||||
uint32 GetEquipmentColor(uint8 material_slot) const;
|
||||
|
||||
// Static Class Methods
|
||||
static void SaveBotGroup(Group* botGroup, std::string botGroupName, std::string* errorMessage);
|
||||
static void DeleteBotGroup(std::string botGroupName, std::string* errorMessage);
|
||||
static std::list<BotGroup> LoadBotGroup(std::string botGroupName, std::string* errorMessage);
|
||||
static uint32 CanLoadBotGroup(uint32 botOwnerCharacterId, std::string botGroupName, std::string* errorMessage);
|
||||
static uint32 GetBotGroupIdByBotGroupName(std::string botGroupName, std::string* errorMessage);
|
||||
static uint32 GetBotGroupLeaderIdByBotGroupName(std::string botGroupName);
|
||||
static std::list<BotGroupList> GetBotGroupListByBotOwnerCharacterId(uint32 botOwnerCharacterId, std::string* errorMessage);
|
||||
static bool DoesBotGroupNameExist(std::string botGroupName);
|
||||
//static void DestroyBotRaidObjects(Client* client); // Can be removed after bot raids are dumped
|
||||
static uint32 GetBotIDByBotName(std::string botName);
|
||||
static Bot* LoadBot(uint32 botID, std::string* errorMessage);
|
||||
static std::list<BotsAvailableList> GetBotList(uint32 botOwnerCharacterID, std::string* errorMessage);
|
||||
static void ProcessBotCommands(Client *c, const Seperator *sep);
|
||||
static std::list<SpawnedBotsList> ListSpawnedBots(uint32 characterID, std::string* errorMessage);
|
||||
static uint32 SpawnedBotCount(uint32 botOwnerCharacterID, std::string* errorMessage);
|
||||
static uint32 CreatedBotCount(uint32 botOwnerCharacterID, std::string* errorMessage);
|
||||
static uint32 AllowedBotSpawns(uint32 botOwnerCharacterID, std::string* errorMessage);
|
||||
static uint32 GetBotOwnerCharacterID(uint32 botID, std::string* errorMessage);
|
||||
//static bool SetBotOwnerCharacterID(uint32 botID, uint32 botOwnerCharacterID, std::string* errorMessage);
|
||||
static std::string ClassIdToString(uint16 classId);
|
||||
static std::string RaceIdToString(uint16 raceId);
|
||||
static bool IsBotAttackAllowed(Mob* attacker, Mob* target, bool& hasRuleDefined);
|
||||
static void BotGroupOrderFollow(Group* group, Client* client);
|
||||
static void BotGroupOrderGuard(Group* group, Client* client);
|
||||
static void BotGroupOrderAttack(Group* group, Mob* target, Client* client);
|
||||
static void BotGroupSummon(Group* group, Client* client);
|
||||
static Bot* GetBotByBotClientOwnerAndBotName(Client* c, std::string botName);
|
||||
static void ProcessBotGroupInvite(Client* c, std::string botName);
|
||||
static void ProcessBotGroupDisband(Client* c, std::string botName);
|
||||
static void BotOrderCampAll(Client* c);
|
||||
static void BotHealRotationsClear( Client* c );
|
||||
static void ProcessBotInspectionRequest(Bot* inspectedBot, Client* client);
|
||||
static std::list<uint32> GetGroupedBotsByGroupId(uint32 groupId, std::string* errorMessage);
|
||||
static void LoadAndSpawnAllZonedBots(Client* botOwner);
|
||||
static bool GroupHasBot(Group* group);
|
||||
static Bot* GetFirstBotInGroup(Group* group);
|
||||
static void ProcessClientZoneChange(Client* botOwner);
|
||||
static void ProcessBotOwnerRefDelete(Mob* botOwner); // Removes a Client* reference when the Client object is destroyed
|
||||
static void ProcessGuildInvite(Client* guildOfficer, Bot* botToGuild); // Processes a client's request to guild a bot
|
||||
static bool ProcessGuildRemoval(Client* guildOfficer, std::string botName); // Processes a client's request to deguild a bot
|
||||
static int32 GetSpellRecastTimer(Bot *caster, int timer_index);
|
||||
static bool CheckSpellRecastTimers(Bot *caster, int SpellIndex);
|
||||
static int32 GetDisciplineRecastTimer(Bot *caster, int timer_index);
|
||||
static bool CheckDisciplineRecastTimers(Bot *caster, int timer_index);
|
||||
static uint32 GetDisciplineRemainingTime(Bot *caster, int timer_index);
|
||||
static std::list<BotSpell> GetBotSpellsForSpellEffect(Bot* botCaster, int spellEffect);
|
||||
static std::list<BotSpell> GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster, int spellEffect, SpellTargetType targetType);
|
||||
static std::list<BotSpell> GetBotSpellsBySpellType(Bot* botCaster, uint16 spellType);
|
||||
static BotSpell GetFirstBotSpellBySpellType(Bot* botCaster, uint16 spellType);
|
||||
static BotSpell GetBestBotSpellForFastHeal(Bot* botCaster);
|
||||
static BotSpell GetBestBotSpellForHealOverTime(Bot* botCaster);
|
||||
static BotSpell GetBestBotSpellForPercentageHeal(Bot* botCaster);
|
||||
static BotSpell GetBestBotSpellForRegularSingleTargetHeal(Bot* botCaster);
|
||||
static BotSpell GetFirstBotSpellForSingleTargetHeal(Bot* botCaster);
|
||||
static BotSpell GetBestBotSpellForGroupHealOverTime(Bot* botCaster);
|
||||
static BotSpell GetBestBotSpellForGroupCompleteHeal(Bot* botCaster);
|
||||
static BotSpell GetBestBotSpellForGroupHeal(Bot* botCaster);
|
||||
static BotSpell GetBestBotSpellForMagicBasedSlow(Bot* botCaster);
|
||||
static BotSpell GetBestBotSpellForDiseaseBasedSlow(Bot* botCaster);
|
||||
static Mob* GetFirstIncomingMobToMez(Bot* botCaster, BotSpell botSpell);
|
||||
static BotSpell GetBestBotSpellForMez(Bot* botCaster);
|
||||
static BotSpell GetBestBotMagicianPetSpell(Bot* botCaster);
|
||||
static std::string GetBotMagicianPetType(Bot* botCaster);
|
||||
static BotSpell GetBestBotSpellForNukeByTargetType(Bot* botCaster, SpellTargetType targetType);
|
||||
static BotSpell GetBestBotSpellForStunByTargetType(Bot* botCaster, SpellTargetType targetType);
|
||||
static BotSpell GetBestBotWizardNukeSpellByTargetResists(Bot* botCaster, Mob* target);
|
||||
static BotSpell GetDebuffBotSpell(Bot* botCaster, Mob* target);
|
||||
static BotSpell GetBestBotSpellForCure(Bot* botCaster, Mob* target);
|
||||
static BotSpell GetBestBotSpellForResistDebuff(Bot* botCaster, Mob* target);
|
||||
static NPCType CreateDefaultNPCTypeStructForBot(std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender);
|
||||
static std::list<Bot*> GetBotsInHealRotation( Bot* leader );
|
||||
|
||||
// Static Bot Group Methods
|
||||
static bool AddBotToGroup(Bot* bot, Group* group);
|
||||
static bool RemoveBotFromGroup(Bot* bot, Group* group);
|
||||
static bool BotGroupCreate(std::string botGroupLeaderName);
|
||||
static bool BotGroupCreate(Bot* botGroupLeader);
|
||||
static bool GroupHasClass(Group* group, uint8 classId);
|
||||
static bool GroupHasClericClass(Group* group) { return GroupHasClass(group, CLERIC); }
|
||||
static bool GroupHasDruidClass(Group* group) { return GroupHasClass(group, DRUID); }
|
||||
static bool GroupHasShamanClass(Group* group) { return GroupHasClass(group, SHAMAN); }
|
||||
static bool GroupHasEnchanterClass(Group* group) { return GroupHasClass(group, ENCHANTER); }
|
||||
static bool GroupHasPriestClass(Group* group) { return GroupHasClass(group, CLERIC | DRUID | SHAMAN); }
|
||||
static void BotGroupSay(Mob *speaker, const char *msg, ...);
|
||||
|
||||
// "GET" Class Methods
|
||||
uint32 GetBotID() const { return _botID; }
|
||||
uint32 GetBotOwnerCharacterID() { return _botOwnerCharacterID; }
|
||||
uint32 GetBotSpellID() { return npc_spells_id; }
|
||||
Mob* GetBotOwner() { return this->_botOwner; }
|
||||
uint32 GetBotArcheryRange();
|
||||
ItemInst* GetBotItem(uint32 slotID);
|
||||
virtual bool GetSpawnStatus() { return _spawnStatus; }
|
||||
uint8 GetPetChooserID() { return _petChooserID; }
|
||||
bool IsPetChooser() { return _petChooser; }
|
||||
bool IsBotArcher() { return _botArcher; }
|
||||
bool IsBotCharmer() { return _botCharmer; }
|
||||
virtual bool IsBot() const { return true; }
|
||||
bool GetRangerAutoWeaponSelect() { return _rangerAutoWeaponSelect; }
|
||||
BotRoleType GetBotRole() { return _botRole; }
|
||||
BotStanceType GetBotStance() { return _botStance; }
|
||||
uint8 GetChanceToCastBySpellType(uint16 spellType);
|
||||
bool IsGroupPrimaryHealer();
|
||||
bool IsGroupPrimarySlower();
|
||||
bool IsBotCaster() { return (GetClass() == CLERIC || GetClass() == DRUID || GetClass() == SHAMAN || GetClass() == NECROMANCER || GetClass() == WIZARD || GetClass() == MAGICIAN || GetClass() == ENCHANTER); }
|
||||
bool IsBotINTCaster() { return (GetClass() == NECROMANCER || GetClass() == WIZARD || GetClass() == MAGICIAN || GetClass() == ENCHANTER); }
|
||||
bool IsBotWISCaster() { return (GetClass() == CLERIC || GetClass() == DRUID || GetClass() == SHAMAN); }
|
||||
bool CanHeal();
|
||||
int GetRawACNoShield(int &shield_ac);
|
||||
void LoadAAs();
|
||||
uint32 GetAA(uint32 aa_id);
|
||||
void ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon);
|
||||
bool GetHasBeenSummoned() { return _hasBeenSummoned; }
|
||||
float GetPreSummonX() { return _preSummonX; }
|
||||
float GetPreSummonY() { return _preSummonY; }
|
||||
float GetPreSummonZ() { return _preSummonZ; }
|
||||
bool GetGroupMessagesOn() { return _groupMessagesOn; }
|
||||
bool GetInHealRotation() { return _isInHealRotation; }
|
||||
bool GetHealRotationActive() { return (GetInHealRotation() && _isHealRotationActive); }
|
||||
bool GetHealRotationUseFastHeals() { return _healRotationUseFastHeals; }
|
||||
bool GetHasHealedThisCycle() { return _hasHealedThisCycle; }
|
||||
Mob* GetHealRotationTarget();
|
||||
Mob* GetHealRotationTarget(uint8 index);
|
||||
Bot* GetHealRotationLeader();
|
||||
Bot* GetNextHealRotationMember();
|
||||
Bot* GetPrevHealRotationMember();
|
||||
uint8 GetNumHealRotationMembers () { return _numHealRotationMembers; }
|
||||
uint32 GetHealRotationNextHealTime() { return _healRotationNextHeal; }
|
||||
uint32 GetHealRotationTimer () { return _healRotationTimer; }
|
||||
inline virtual int16 GetAC() const { return AC; }
|
||||
inline virtual int16 GetSTR() const { return STR; }
|
||||
inline virtual int16 GetSTA() const { return STA; }
|
||||
inline virtual int16 GetDEX() const { return DEX; }
|
||||
inline virtual int16 GetAGI() const { return AGI; }
|
||||
inline virtual int16 GetINT() const { return INT; }
|
||||
inline virtual int16 GetWIS() const { return WIS; }
|
||||
inline virtual int16 GetCHA() const { return CHA; }
|
||||
inline virtual int16 GetMR() const { return MR; }
|
||||
inline virtual int16 GetFR() const { return FR; }
|
||||
inline virtual int16 GetDR() const { return DR; }
|
||||
inline virtual int16 GetPR() const { return PR; }
|
||||
inline virtual int16 GetCR() const { return CR; }
|
||||
inline virtual int16 GetCorrup() const { return Corrup; }
|
||||
//Heroic
|
||||
inline virtual int16 GetHeroicSTR() const { return itembonuses.HeroicSTR; }
|
||||
inline virtual int16 GetHeroicSTA() const { return itembonuses.HeroicSTA; }
|
||||
inline virtual int16 GetHeroicDEX() const { return itembonuses.HeroicDEX; }
|
||||
inline virtual int16 GetHeroicAGI() const { return itembonuses.HeroicAGI; }
|
||||
inline virtual int16 GetHeroicINT() const { return itembonuses.HeroicINT; }
|
||||
inline virtual int16 GetHeroicWIS() const { return itembonuses.HeroicWIS; }
|
||||
inline virtual int16 GetHeroicCHA() const { return itembonuses.HeroicCHA; }
|
||||
inline virtual int16 GetHeroicMR() const { return itembonuses.HeroicMR; }
|
||||
inline virtual int16 GetHeroicFR() const { return itembonuses.HeroicFR; }
|
||||
inline virtual int16 GetHeroicDR() const { return itembonuses.HeroicDR; }
|
||||
inline virtual int16 GetHeroicPR() const { return itembonuses.HeroicPR; }
|
||||
inline virtual int16 GetHeroicCR() const { return itembonuses.HeroicCR; }
|
||||
inline virtual int16 GetHeroicCorrup() const { return itembonuses.HeroicCorrup; }
|
||||
// Mod2
|
||||
inline virtual int16 GetShielding() const { return itembonuses.MeleeMitigation; }
|
||||
inline virtual int16 GetSpellShield() const { return itembonuses.SpellShield; }
|
||||
inline virtual int16 GetDoTShield() const { return itembonuses.DoTShielding; }
|
||||
inline virtual int16 GetStunResist() const { return itembonuses.StunResist; }
|
||||
inline virtual int16 GetStrikeThrough() const { return itembonuses.StrikeThrough; }
|
||||
inline virtual int16 GetAvoidance() const { return itembonuses.AvoidMeleeChance; }
|
||||
inline virtual int16 GetAccuracy() const { return itembonuses.HitChance; }
|
||||
inline virtual int16 GetCombatEffects() const { return itembonuses.ProcChance; }
|
||||
inline virtual int16 GetDS() const { return itembonuses.DamageShield; }
|
||||
// Mod3
|
||||
inline virtual int16 GetHealAmt() const { return itembonuses.HealAmt; }
|
||||
inline virtual int16 GetSpellDmg() const { return itembonuses.SpellDmg; }
|
||||
inline virtual int16 GetClair() const { return itembonuses.Clairvoyance; }
|
||||
inline virtual int16 GetDSMit() const { return itembonuses.DSMitigation; }
|
||||
|
||||
inline virtual int16 GetSingMod() const { return itembonuses.singingMod; }
|
||||
inline virtual int16 GetBrassMod() const { return itembonuses.brassMod; }
|
||||
inline virtual int16 GetPercMod() const { return itembonuses.percussionMod; }
|
||||
inline virtual int16 GetStringMod() const { return itembonuses.stringedMod; }
|
||||
inline virtual int16 GetWindMod() const { return itembonuses.windMod; }
|
||||
|
||||
inline virtual int16 GetDelayDeath() const { return aabonuses.DelayDeath + spellbonuses.DelayDeath + itembonuses.DelayDeath; }
|
||||
|
||||
inline InspectMessage_Struct& GetInspectMessage() { return _botInspectMessage; }
|
||||
inline const InspectMessage_Struct& GetInspectMessage() const { return _botInspectMessage; }
|
||||
|
||||
// "SET" Class Methods
|
||||
void SetBotSpellID(uint32 newSpellID);
|
||||
virtual void SetSpawnStatus(bool spawnStatus) { _spawnStatus = spawnStatus; }
|
||||
void SetPetChooserID(uint8 id) { _petChooserID = id; }
|
||||
void SetBotArcher(bool a) { _botArcher = a; }
|
||||
void SetBotCharmer(bool c) { _botCharmer = c; }
|
||||
void SetPetChooser(bool p) { _petChooser = p; }
|
||||
void SetBotOwner(Mob* botOwner) { this->_botOwner = botOwner; }
|
||||
// void SetBotOwnerCharacterID(uint32 botOwnerCharacterID) { _botOwnerCharacterID = botOwnerCharacterID; }
|
||||
void SetRangerAutoWeaponSelect(bool enable) { GetClass() == RANGER ? _rangerAutoWeaponSelect = enable : _rangerAutoWeaponSelect = false; }
|
||||
void SetBotRole(BotRoleType botRole) { _botRole = botRole; }
|
||||
void SetBotStance(BotStanceType botStance) { _botStance = botStance; }
|
||||
void SetSpellRecastTimer(int timer_index, int32 recast_delay);
|
||||
void SetDisciplineRecastTimer(int timer_index, int32 recast_delay);
|
||||
void SetHasBeenSummoned(bool s);
|
||||
void SetPreSummonX(float x) { _preSummonX = x; }
|
||||
void SetPreSummonY(float y) { _preSummonY = y; }
|
||||
void SetPreSummonZ(float z) { _preSummonZ = z; }
|
||||
void SetGroupMessagesOn(bool groupMessagesOn) { _groupMessagesOn = groupMessagesOn; }
|
||||
void SetInHealRotation( bool inRotation ) { _isInHealRotation = inRotation; }
|
||||
void SetHealRotationActive( bool isActive ) { _isHealRotationActive = isActive; }
|
||||
void SetHealRotationUseFastHeals( bool useFastHeals ) { _healRotationUseFastHeals = useFastHeals; }
|
||||
void SetHasHealedThisCycle( bool hasHealed ) { _hasHealedThisCycle = hasHealed; }
|
||||
void SetHealRotationLeader( Bot* leader );
|
||||
void SetNextHealRotationMember( Bot* healer );
|
||||
void SetPrevHealRotationMember( Bot* healer );
|
||||
void SetHealRotationNextHealTime( uint32 nextHealTime ) { _healRotationNextHeal = nextHealTime; }
|
||||
void SetHealRotationTimer( uint32 timer ) { _healRotationTimer = timer; }
|
||||
void SetNumHealRotationMembers( uint8 numMembers ) { _numHealRotationMembers = numMembers; }
|
||||
|
||||
// Class Destructors
|
||||
virtual ~Bot();
|
||||
|
||||
protected:
|
||||
virtual void PetAIProcess();
|
||||
static NPCType FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender, float size, uint32 face, uint32 hairStyle, uint32 hairColor, uint32 eyeColor, uint32 eyeColor2, uint32 beardColor, uint32 beard, uint32 drakkinHeritage, uint32 drakkinTattoo, uint32 drakkinDetails, int32 hp, int32 mana, int16 mr, int16 cr, int16 dr, int16 fr, int16 pr, int16 corrup, int16 ac, uint16 str, uint16 sta, uint16 dex, uint16 agi, uint16 _int, uint16 wis, uint16 cha, uint16 attack);
|
||||
virtual void BotMeditate(bool isSitting);
|
||||
virtual void BotRangedAttack(Mob* other);
|
||||
virtual bool CheckBotDoubleAttack(bool Triple = false);
|
||||
virtual int16 GetBotFocusEffect(BotfocusType bottype, uint16 spell_id);
|
||||
virtual int16 CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spell_id, bool best_focus=false);
|
||||
virtual int16 CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id);
|
||||
virtual void PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* client);
|
||||
virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0);
|
||||
virtual float GetMaxMeleeRangeToTarget(Mob* target);
|
||||
|
||||
static void SetBotGuildMembership(uint32 botId, uint32 guildid, uint8 rank);
|
||||
|
||||
private:
|
||||
// Class Members
|
||||
uint32 _botID;
|
||||
uint32 _botOwnerCharacterID;
|
||||
//uint32 _botSpellID;
|
||||
bool _spawnStatus;
|
||||
Mob* _botOwner;
|
||||
bool _botOrderAttack;
|
||||
bool _botArcher;
|
||||
bool _botCharmer;
|
||||
bool _petChooser;
|
||||
uint8 _petChooserID;
|
||||
bool berserk;
|
||||
Inventory m_inv;
|
||||
double _lastTotalPlayTime;
|
||||
time_t _startTotalPlayTime;
|
||||
Mob* _previousTarget;
|
||||
uint32 _guildId;
|
||||
uint8 _guildRank;
|
||||
std::string _guildName;
|
||||
uint32 _lastZoneId;
|
||||
bool _rangerAutoWeaponSelect;
|
||||
BotRoleType _botRole;
|
||||
BotStanceType _botStance;
|
||||
BotStanceType _baseBotStance;
|
||||
unsigned int RestRegenHP;
|
||||
unsigned int RestRegenMana;
|
||||
unsigned int RestRegenEndurance;
|
||||
Timer rest_timer;
|
||||
int32 base_end;
|
||||
int32 cur_end;
|
||||
int32 max_end;
|
||||
int16 end_regen;
|
||||
uint32 timers[MaxTimer];
|
||||
bool _hasBeenSummoned;
|
||||
float _preSummonX;
|
||||
float _preSummonY;
|
||||
float _preSummonZ;
|
||||
uint8 _spellCastingChances[MaxStances][MaxSpellTypes];
|
||||
bool _groupMessagesOn;
|
||||
bool _isInHealRotation;
|
||||
bool _isHealRotationActive;
|
||||
bool _healRotationUseFastHeals;
|
||||
bool _hasHealedThisCycle;
|
||||
uint32 _healRotationTimer;
|
||||
uint32 _healRotationNextHeal;
|
||||
//char _healRotationTargets[MaxHealRotationTargets][64];
|
||||
uint16 _healRotationTargets[MaxHealRotationTargets];
|
||||
uint32 _healRotationLeader;
|
||||
uint32 _healRotationMemberNext;
|
||||
uint32 _healRotationMemberPrev;
|
||||
uint8 _numHealRotationMembers;
|
||||
std::map<uint32, BotAA> botAAs;
|
||||
InspectMessage_Struct _botInspectMessage;
|
||||
|
||||
// Private "base stats" Members
|
||||
int16 _baseMR;
|
||||
int16 _baseCR;
|
||||
int16 _baseDR;
|
||||
int16 _baseFR;
|
||||
int16 _basePR;
|
||||
int16 _baseCorrup;
|
||||
int _baseAC;
|
||||
int16 _baseSTR;
|
||||
int16 _baseSTA;
|
||||
int16 _baseDEX;
|
||||
int16 _baseAGI;
|
||||
int16 _baseINT;
|
||||
int16 _baseWIS;
|
||||
int16 _baseCHA;
|
||||
int16 _baseATK;
|
||||
uint16 _baseRace; // Necessary to preserve the race otherwise bots get their race updated in the db when they get an illusion.
|
||||
uint8 _baseGender; // Bots gender. Necessary to preserve the original value otherwise it can be changed by illusions.
|
||||
|
||||
// Class Methods
|
||||
int16 acmod();
|
||||
void GenerateBaseStats();
|
||||
void GenerateAppearance();
|
||||
void GenerateArmorClass();
|
||||
int32 GenerateBaseHitPoints();
|
||||
void GenerateAABonuses(StatBonuses* newbon);
|
||||
int32 GenerateBaseManaPoints();
|
||||
void GenerateSpecialAttacks();
|
||||
void SetBotID(uint32 botID);
|
||||
|
||||
// Private "Inventory" Methods
|
||||
void GetBotItems(std::string* errorMessage, Inventory &inv);
|
||||
void BotRemoveEquipItem(int slot);
|
||||
void BotAddEquipItem(int slot, uint32 id);
|
||||
uint32 GetBotItemBySlot(uint32 slotID);
|
||||
void RemoveBotItemBySlot(uint32 slotID, std::string* errorMessage);
|
||||
void SetBotItemInSlot(uint32 slotID, uint32 itemID, const ItemInst* inst, std::string* errorMessage);
|
||||
uint32 GetBotItemsCount(std::string* errorMessage);
|
||||
uint32 GetTotalPlayTime();
|
||||
void SaveBuffs(); // Saves existing buffs to the database to persist zoning and camping
|
||||
void LoadBuffs(); // Retrieves saved buffs from the database on spawning
|
||||
void LoadPetBuffs(SpellBuff_Struct* petBuffs, uint32 botPetSaveId);
|
||||
void SavePetBuffs(SpellBuff_Struct* petBuffs, uint32 botPetSaveId);
|
||||
void LoadPetItems(uint32* petItems, uint32 botPetSaveId);
|
||||
void SavePetItems(uint32* petItems, uint32 botPetSaveId);
|
||||
void LoadPetStats(std::string* petName, uint16* petMana, uint16* petHitPoints, uint32* botPetId, uint32 botPetSaveId);
|
||||
uint32 SavePetStats(std::string petName, uint16 petMana, uint16 petHitPoints, uint32 botPetId);
|
||||
void LoadPet(); // Load and spawn bot pet if there is one
|
||||
void SavePet(); // Save and depop bot pet if there is one
|
||||
uint32 GetPetSaveId();
|
||||
void DeletePetBuffs(uint32 botPetSaveId);
|
||||
void DeletePetItems(uint32 botPetSaveId);
|
||||
void DeletePetStats(uint32 botPetSaveId);
|
||||
void LoadGuildMembership(uint32* guildId, uint8* guildRank, std::string* guildName);
|
||||
void LoadStance();
|
||||
void SaveStance();
|
||||
void LoadTimers();
|
||||
void SaveTimers();
|
||||
};
|
||||
|
||||
#endif // BOTS
|
||||
|
||||
#endif // BOT_H
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef BOT_STRUCTS
|
||||
#define BOT_STRUCTS
|
||||
|
||||
#ifdef BOTS
|
||||
|
||||
#include "../common/types.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
struct BotsAvailableList {
|
||||
uint32 BotID;
|
||||
char BotName[64];
|
||||
uint16 BotClass;
|
||||
uint8 BotLevel;
|
||||
uint16 BotRace;
|
||||
};
|
||||
|
||||
struct BotGroup {
|
||||
uint32 BotGroupID;
|
||||
uint32 BotID;
|
||||
};
|
||||
|
||||
struct BotGroupList {
|
||||
std::string BotGroupName;
|
||||
std::string BotGroupLeaderName;
|
||||
};
|
||||
|
||||
struct SpawnedBotsList {
|
||||
char BotName[64];
|
||||
char ZoneName[64];
|
||||
uint32 BotLeaderCharID;
|
||||
};
|
||||
|
||||
struct BotSpell {
|
||||
uint16 SpellId;
|
||||
int SpellIndex;
|
||||
int16 ManaCost;
|
||||
};
|
||||
|
||||
struct BotAA {
|
||||
uint32 aa_id;
|
||||
uint8 req_level;
|
||||
uint8 total_levels;
|
||||
};
|
||||
|
||||
#endif // BOTS
|
||||
|
||||
#endif // BOT_STRUCTS
|
||||
File diff suppressed because it is too large
Load Diff
+7279
File diff suppressed because it is too large
Load Diff
+1439
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,141 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "../common/debug.h"
|
||||
#include "features.h"
|
||||
|
||||
#ifdef CLIENT_LOGS
|
||||
#include "client_logs.h"
|
||||
#include "client.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
ClientLogs client_logs;
|
||||
|
||||
char ClientLogs::_buffer[MAX_CLIENT_LOG_MESSAGE_LENGTH+1];
|
||||
|
||||
void ClientLogs::subscribe(EQEMuLog::LogIDs id, Client *c) {
|
||||
if(id >= EQEMuLog::MaxLogID)
|
||||
return;
|
||||
if(c == NULL)
|
||||
return;
|
||||
|
||||
//make sure they arnt allready subscribed.
|
||||
|
||||
vector<Client *>::iterator cur,end;
|
||||
cur = entries[id].begin();
|
||||
end = entries[id].end();
|
||||
for(; cur != end; cur++) {
|
||||
if(*cur == c) {
|
||||
printf("%s was allready subscribed to %d\n", c->GetName(), id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s has been subscribed to %d\n", c->GetName(), id);
|
||||
entries[id].push_back(c);
|
||||
}
|
||||
|
||||
void ClientLogs::unsubscribe(EQEMuLog::LogIDs id, Client *c) {
|
||||
if(id >= EQEMuLog::MaxLogID)
|
||||
return;
|
||||
if(c == NULL)
|
||||
return;
|
||||
|
||||
vector<Client *>::iterator cur,end;
|
||||
cur = entries[id].begin();
|
||||
end = entries[id].end();
|
||||
for(; cur != end; cur++) {
|
||||
if(*cur == c) {
|
||||
entries[id].erase(cur);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClientLogs::subscribeAll(Client *c) {
|
||||
if(c == NULL)
|
||||
return;
|
||||
int r;
|
||||
for(r = EQEMuLog::Status; r < EQEMuLog::MaxLogID; r++) {
|
||||
subscribe((EQEMuLog::LogIDs)r, c);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientLogs::unsubscribeAll(Client *c) {
|
||||
if(c == NULL)
|
||||
return;
|
||||
int r;
|
||||
for(r = EQEMuLog::Status; r < EQEMuLog::MaxLogID; r++) {
|
||||
unsubscribe((EQEMuLog::LogIDs)r, c);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientLogs::clear() {
|
||||
int r;
|
||||
for(r = EQEMuLog::Status; r < EQEMuLog::MaxLogID; r++) {
|
||||
entries[r].clear();
|
||||
}
|
||||
}
|
||||
|
||||
void ClientLogs::msg(EQEMuLog::LogIDs id, const char *buf) {
|
||||
if(id >= EQEMuLog::MaxLogID)
|
||||
return;
|
||||
vector<Client *>::iterator cur,end;
|
||||
cur = entries[id].begin();
|
||||
end = entries[id].end();
|
||||
for(; cur != end; cur++) {
|
||||
if(!(*cur)->InZone())
|
||||
continue;
|
||||
(*cur)->Message(CLIENT_LOG_CHANNEL, buf);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientLogs::EQEmuIO_buf(EQEMuLog::LogIDs id, const char *buf, uint8 size, uint32 count) {
|
||||
if(size != 1)
|
||||
return; //cannot print multibyte data
|
||||
if(buf[0] == '\n' || buf[0] == '\r')
|
||||
return; //skip new lines...
|
||||
if(count > MAX_CLIENT_LOG_MESSAGE_LENGTH)
|
||||
count = MAX_CLIENT_LOG_MESSAGE_LENGTH;
|
||||
memcpy(_buffer, buf, count);
|
||||
_buffer[count] = '\0';
|
||||
client_logs.msg(id, _buffer);
|
||||
}
|
||||
|
||||
void ClientLogs::EQEmuIO_fmt(EQEMuLog::LogIDs id, const char *fmt, va_list ap) {
|
||||
if(fmt[0] == '\n' || fmt[0] == '\r')
|
||||
return; //skip new lines...
|
||||
vsnprintf(_buffer, MAX_CLIENT_LOG_MESSAGE_LENGTH, fmt, ap);
|
||||
_buffer[MAX_CLIENT_LOG_MESSAGE_LENGTH] = '\0';
|
||||
client_logs.msg(id, _buffer);
|
||||
}
|
||||
|
||||
void ClientLogs::EQEmuIO_pva(EQEMuLog::LogIDs id, const char *prefix, const char *fmt, va_list ap) {
|
||||
if(fmt[0] == '\n' || fmt[0] == '\r')
|
||||
return; //skip new lines...
|
||||
char *buf = _buffer;
|
||||
int plen = snprintf(buf, MAX_CLIENT_LOG_MESSAGE_LENGTH, prefix);
|
||||
buf += plen;
|
||||
vsnprintf(buf, MAX_CLIENT_LOG_MESSAGE_LENGTH-plen, fmt, ap);
|
||||
_buffer[MAX_CLIENT_LOG_MESSAGE_LENGTH] = '\0';
|
||||
client_logs.msg(id, _buffer);
|
||||
}
|
||||
|
||||
#endif //CLIENT_LOGS
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef CLIENT_LOGS_H
|
||||
#define CLIENT_LOGS_H
|
||||
#include "../common/debug.h"
|
||||
#include "features.h"
|
||||
|
||||
#ifdef CLIENT_LOGS
|
||||
#include "../common/eq_packet_structs.h"
|
||||
|
||||
#define CLIENT_LOG_CHANNEL MT_Chat10Echo
|
||||
|
||||
//trim messages to this length before sending to any clients
|
||||
#define MAX_CLIENT_LOG_MESSAGE_LENGTH 512
|
||||
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
class Client;
|
||||
|
||||
class ClientLogs {
|
||||
public:
|
||||
static void EQEmuIO_buf(EQEMuLog::LogIDs id, const char *buf, uint8 size, uint32 count);
|
||||
static void EQEmuIO_fmt(EQEMuLog::LogIDs id, const char *fmt, va_list ap);
|
||||
static void EQEmuIO_pva(EQEMuLog::LogIDs id, const char *prefix, const char *fmt, va_list ap);
|
||||
|
||||
void subscribe(EQEMuLog::LogIDs id, Client *c);
|
||||
void unsubscribe(EQEMuLog::LogIDs id, Client *c);
|
||||
void subscribeAll(Client *c);
|
||||
void unsubscribeAll(Client *c);
|
||||
void clear(); //unsubscribes everybody
|
||||
|
||||
void msg(EQEMuLog::LogIDs id, const char *buf);
|
||||
|
||||
protected:
|
||||
|
||||
vector<Client *> entries[EQEMuLog::MaxLogID];
|
||||
|
||||
static char _buffer[MAX_CLIENT_LOG_MESSAGE_LENGTH+1];
|
||||
};
|
||||
|
||||
extern ClientLogs client_logs;
|
||||
|
||||
#endif //CLIENT_LOGS
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+13842
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,290 @@
|
||||
void Handle_Connect_OP_SetDataRate(const EQApplicationPacket *app);
|
||||
void Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app);
|
||||
void Handle_Connect_OP_SetServerFilter(const EQApplicationPacket *app);
|
||||
void Handle_Connect_OP_SendAATable(const EQApplicationPacket *app);
|
||||
void Handle_Connect_OP_SendTributes(const EQApplicationPacket *app);
|
||||
void Handle_Connect_OP_SendGuildTributes(const EQApplicationPacket *app);
|
||||
void Handle_Connect_OP_SendAAStats(const EQApplicationPacket *app);
|
||||
void Handle_Connect_0x3e33(const EQApplicationPacket *app);
|
||||
void Handle_Connect_OP_ReqClientSpawn(const EQApplicationPacket *app);
|
||||
void Handle_Connect_OP_SendExpZonein(const EQApplicationPacket *app);
|
||||
void Handle_Connect_OP_WorldObjectsSent(const EQApplicationPacket *app);
|
||||
void Handle_Connect_OP_ZoneComplete(const EQApplicationPacket *app);
|
||||
void Handle_Connect_OP_ReqNewZone(const EQApplicationPacket *app);
|
||||
void Handle_Connect_OP_SpawnAppearance(const EQApplicationPacket *app);
|
||||
void Handle_Connect_OP_WearChange(const EQApplicationPacket *app);
|
||||
void Handle_Connect_OP_ClientUpdate(const EQApplicationPacket *app);
|
||||
void Handle_Connect_OP_ClientError(const EQApplicationPacket *app);
|
||||
void Handle_Connect_OP_ApproveZone(const EQApplicationPacket *app);
|
||||
void Handle_Connect_OP_ClientReady(const EQApplicationPacket *app);
|
||||
void Handle_Connect_OP_UpdateAA(const EQApplicationPacket *app);
|
||||
void Handle_Connect_OP_TGB(const EQApplicationPacket *app);
|
||||
void Handle_OP_ClientUpdate(const EQApplicationPacket *app);
|
||||
void Handle_OP_AutoAttack(const EQApplicationPacket *app);
|
||||
void Handle_OP_AutoAttack2(const EQApplicationPacket *app);
|
||||
void Handle_OP_Consent(const EQApplicationPacket *app);
|
||||
void Handle_OP_ConsentDeny(const EQApplicationPacket *app);
|
||||
void Handle_OP_TargetMouse(const EQApplicationPacket *app);
|
||||
void Handle_OP_TargetCommand(const EQApplicationPacket *app);
|
||||
void Handle_OP_Shielding(const EQApplicationPacket *app);
|
||||
void Handle_OP_Jump(const EQApplicationPacket *app);
|
||||
void Handle_OP_AdventureInfoRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_AdventureRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_LDoNButton(const EQApplicationPacket *app);
|
||||
void Handle_OP_LeaveAdventure(const EQApplicationPacket *app);
|
||||
void Handle_OP_Consume(const EQApplicationPacket *app);
|
||||
void Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_AdventureMerchantRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app);
|
||||
void Handle_OP_ConsiderCorpse(const EQApplicationPacket *app);
|
||||
void Handle_OP_Consider(const EQApplicationPacket *app);
|
||||
void Handle_OP_Begging(const EQApplicationPacket *app);
|
||||
void Handle_OP_TestBuff(const EQApplicationPacket *app);
|
||||
void Handle_OP_Surname(const EQApplicationPacket *app);
|
||||
void Handle_OP_ClearSurname(const EQApplicationPacket *app);
|
||||
void Handle_OP_YellForHelp(const EQApplicationPacket *app);
|
||||
void Handle_OP_Assist(const EQApplicationPacket *app);
|
||||
void Handle_OP_AssistGroup(const EQApplicationPacket *app);
|
||||
void Handle_OP_GMTraining(const EQApplicationPacket *app);
|
||||
void Handle_OP_GMEndTraining(const EQApplicationPacket *app);
|
||||
void Handle_OP_GMTrainSkill(const EQApplicationPacket *app);
|
||||
void Handle_OP_DuelResponse(const EQApplicationPacket *app);
|
||||
void Handle_OP_DuelResponse2(const EQApplicationPacket *app);
|
||||
void Handle_OP_RequestDuel(const EQApplicationPacket *app);
|
||||
void Handle_OP_SpawnAppearance(const EQApplicationPacket *app);
|
||||
void Handle_OP_BazaarInspect(const EQApplicationPacket *app);
|
||||
void Handle_OP_Death(const EQApplicationPacket *app);
|
||||
void Handle_OP_MoveCoin(const EQApplicationPacket *app);
|
||||
void Handle_OP_ItemLinkClick(const EQApplicationPacket *app);
|
||||
void Handle_OP_ItemLinkResponse(const EQApplicationPacket *app);
|
||||
void Handle_OP_MoveItem(const EQApplicationPacket *app);
|
||||
void Handle_OP_Camp(const EQApplicationPacket *app);
|
||||
void Handle_OP_Logout(const EQApplicationPacket *app);
|
||||
void Handle_OP_SenseHeading(const EQApplicationPacket *app);
|
||||
void Handle_OP_LDoNOpen(const EQApplicationPacket *app);
|
||||
void Handle_OP_LDoNDisarmTraps(const EQApplicationPacket *app);
|
||||
void Handle_OP_LDoNSenseTraps(const EQApplicationPacket *app);
|
||||
void Handle_OP_LDoNInspect(const EQApplicationPacket *app);
|
||||
void Handle_OP_LDoNPickLock(const EQApplicationPacket *app);
|
||||
void Handle_OP_FeignDeath(const EQApplicationPacket *app);
|
||||
void Handle_OP_Sneak(const EQApplicationPacket *app);
|
||||
void Handle_OP_Hide(const EQApplicationPacket *app);
|
||||
void Handle_OP_ChannelMessage(const EQApplicationPacket *app);
|
||||
void Handle_OP_WearChange(const EQApplicationPacket *app);
|
||||
void Handle_OP_ZoneChange(const EQApplicationPacket *app);
|
||||
void Handle_OP_DeleteSpawn(const EQApplicationPacket *app);
|
||||
void Handle_OP_SaveOnZoneReq(const EQApplicationPacket *app);
|
||||
void Handle_OP_Save(const EQApplicationPacket *app);
|
||||
void Handle_OP_WhoAllRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_GMZoneRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_GMZoneRequest2(const EQApplicationPacket *app);
|
||||
void Handle_OP_EndLootRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_LootRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_Dye(const EQApplicationPacket *app);
|
||||
void Handle_OP_LootItem(const EQApplicationPacket *app);
|
||||
void Handle_OP_GuildDelete(const EQApplicationPacket *app);
|
||||
void Handle_OP_GuildPublicNote(const EQApplicationPacket *app);
|
||||
void Handle_OP_GetGuildsList(const EQApplicationPacket *app);
|
||||
void Handle_OP_SetGuildMOTD(const EQApplicationPacket *app);
|
||||
void Handle_OP_GuildPeace(const EQApplicationPacket *app);
|
||||
void Handle_OP_GuildWar(const EQApplicationPacket *app);
|
||||
void Handle_OP_GuildLeader(const EQApplicationPacket *app);
|
||||
void Handle_OP_GuildDemote(const EQApplicationPacket *app);
|
||||
void Handle_OP_GuildInvite(const EQApplicationPacket *app);
|
||||
void Handle_OP_GuildRemove(const EQApplicationPacket *app);
|
||||
void Handle_OP_GetGuildMOTD(const EQApplicationPacket *app);
|
||||
void Handle_OP_GuildManageBanker(const EQApplicationPacket *app);
|
||||
void Handle_OP_GuildInviteAccept(const EQApplicationPacket *app);
|
||||
void Handle_OP_ManaChange(const EQApplicationPacket *app);
|
||||
void Handle_OP_MemorizeSpell(const EQApplicationPacket *app);
|
||||
void Handle_OP_SwapSpell(const EQApplicationPacket *app);
|
||||
void Handle_OP_CastSpell(const EQApplicationPacket *app);
|
||||
void Handle_OP_DeleteItem(const EQApplicationPacket *app);
|
||||
void Handle_OP_CombatAbility(const EQApplicationPacket *app);
|
||||
void Handle_OP_Taunt(const EQApplicationPacket *app);
|
||||
void Handle_OP_InstillDoubt(const EQApplicationPacket *app);
|
||||
void Handle_OP_RezzAnswer(const EQApplicationPacket *app);
|
||||
void Handle_OP_GMSummon(const EQApplicationPacket *app);
|
||||
void Handle_OP_TradeRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_TradeRequestAck(const EQApplicationPacket *app);
|
||||
void Handle_OP_CancelTrade(const EQApplicationPacket *app);
|
||||
void Handle_OP_TradeAcceptClick(const EQApplicationPacket *app);
|
||||
void Handle_OP_BoardBoat(const EQApplicationPacket *app);
|
||||
void Handle_OP_LeaveBoat(const EQApplicationPacket *app);
|
||||
void Handle_OP_RandomReq(const EQApplicationPacket *app);
|
||||
void Handle_OP_Buff(const EQApplicationPacket *app);
|
||||
void Handle_OP_GMHideMe(const EQApplicationPacket *app);
|
||||
void Handle_OP_GMNameChange(const EQApplicationPacket *app);
|
||||
void Handle_OP_GMKill(const EQApplicationPacket *app);
|
||||
void Handle_OP_GMLastName(const EQApplicationPacket *app);
|
||||
void Handle_OP_GMToggle(const EQApplicationPacket *app);
|
||||
void Handle_OP_LFGCommand(const EQApplicationPacket *app);
|
||||
void Handle_OP_GMGoto(const EQApplicationPacket *app);
|
||||
void Handle_OP_TraderShop(const EQApplicationPacket *app);
|
||||
void Handle_OP_ShopRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_BazaarSearch(const EQApplicationPacket *app);
|
||||
void Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app);
|
||||
void Handle_OP_ShopPlayerSell(const EQApplicationPacket *app);
|
||||
void Handle_OP_ShopEnd(const EQApplicationPacket *app);
|
||||
// void Handle_OP_CloseContainer(const EQApplicationPacket *app);
|
||||
void Handle_OP_ClickObjectAction(const EQApplicationPacket *app);
|
||||
void Handle_OP_ClickObject(const EQApplicationPacket *app);
|
||||
void Handle_OP_RecipesFavorite(const EQApplicationPacket *app);
|
||||
void Handle_OP_RecipesSearch(const EQApplicationPacket *app);
|
||||
void Handle_OP_RecipeDetails(const EQApplicationPacket *app);
|
||||
void Handle_OP_RecipeAutoCombine(const EQApplicationPacket *app);
|
||||
void Handle_OP_TradeSkillCombine(const EQApplicationPacket *app);
|
||||
void Handle_OP_ItemName(const EQApplicationPacket *app);
|
||||
void Handle_OP_AugmentItem(const EQApplicationPacket *app);
|
||||
void Handle_OP_ClickDoor(const EQApplicationPacket *app);
|
||||
void Handle_OP_CreateObject(const EQApplicationPacket *app);
|
||||
void Handle_OP_FaceChange(const EQApplicationPacket *app);
|
||||
void Handle_OP_GroupInvite(const EQApplicationPacket *app);
|
||||
void Handle_OP_GroupInvite2(const EQApplicationPacket *app);
|
||||
void Handle_OP_GroupAcknowledge(const EQApplicationPacket *app);
|
||||
void Handle_OP_GroupCancelInvite(const EQApplicationPacket *app);
|
||||
void Handle_OP_GroupFollow(const EQApplicationPacket *app);
|
||||
void Handle_OP_GroupFollow2(const EQApplicationPacket *app);
|
||||
void Handle_OP_GroupDisband(const EQApplicationPacket *app);
|
||||
void Handle_OP_GroupDelete(const EQApplicationPacket *app);
|
||||
void Handle_OP_GMEmoteZone(const EQApplicationPacket *app);
|
||||
void Handle_OP_InspectRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_InspectAnswer(const EQApplicationPacket *app);
|
||||
void Handle_OP_InspectMessageUpdate(const EQApplicationPacket *app);
|
||||
void Handle_OP_Medding(const EQApplicationPacket *app);
|
||||
void Handle_OP_DeleteSpell(const EQApplicationPacket *app);
|
||||
void Handle_OP_PetitionBug(const EQApplicationPacket *app);
|
||||
void Handle_OP_Bug(const EQApplicationPacket *app);
|
||||
void Handle_OP_Petition(const EQApplicationPacket *app);
|
||||
void Handle_OP_PetitionCheckIn(const EQApplicationPacket *app);
|
||||
void Handle_OP_PetitionResolve(const EQApplicationPacket *app);
|
||||
void Handle_OP_PetitionDelete(const EQApplicationPacket *app);
|
||||
void Handle_OP_PetCommands(const EQApplicationPacket *app);
|
||||
void Handle_OP_PetitionUnCheckout(const EQApplicationPacket *app);
|
||||
void Handle_OP_PetitionQue(const EQApplicationPacket *app);
|
||||
void Handle_OP_PDeletePetition(const EQApplicationPacket *app);
|
||||
void Handle_OP_PetitionCheckout(const EQApplicationPacket *app);
|
||||
void Handle_OP_PetitionRefresh(const EQApplicationPacket *app);
|
||||
void Handle_OP_ReadBook(const EQApplicationPacket *app);
|
||||
void Handle_OP_Emote(const EQApplicationPacket *app);
|
||||
void Handle_OP_Animation(const EQApplicationPacket *app);
|
||||
void Handle_OP_SetServerFilter(const EQApplicationPacket *app);
|
||||
void Handle_OP_GMDelCorpse(const EQApplicationPacket *app);
|
||||
void Handle_OP_GMKick(const EQApplicationPacket *app);
|
||||
void Handle_OP_GMServers(const EQApplicationPacket *app);
|
||||
void Handle_OP_Illusion(const EQApplicationPacket *app);
|
||||
void Handle_OP_GMBecomeNPC(const EQApplicationPacket *app);
|
||||
void Handle_OP_Fishing(const EQApplicationPacket *app);
|
||||
void Handle_OP_Forage(const EQApplicationPacket *app);
|
||||
void Handle_OP_Mend(const EQApplicationPacket *app);
|
||||
void Handle_OP_EnvDamage(const EQApplicationPacket *app);
|
||||
void Handle_OP_Damage(const EQApplicationPacket *app);
|
||||
void Handle_OP_AAAction(const EQApplicationPacket *app);
|
||||
void Handle_OP_TraderBuy(const EQApplicationPacket *app);
|
||||
void Handle_OP_Trader(const EQApplicationPacket *app);
|
||||
void Handle_OP_GMFind(const EQApplicationPacket *app);
|
||||
void Handle_OP_PickPocket(const EQApplicationPacket *app);
|
||||
void Handle_OP_Bind_Wound(const EQApplicationPacket *app);
|
||||
void Handle_OP_TrackTarget(const EQApplicationPacket *app);
|
||||
void Handle_OP_Track(const EQApplicationPacket *app);
|
||||
void Handle_OP_TrackUnknown(const EQApplicationPacket *app);
|
||||
void Handle_0x0193(const EQApplicationPacket *app);
|
||||
void Handle_0x01e7(const EQApplicationPacket *app);
|
||||
void Handle_OP_ClientError(const EQApplicationPacket *app);
|
||||
void Handle_OP_ReloadUI(const EQApplicationPacket *app);
|
||||
void Handle_OP_TGB(const EQApplicationPacket *app);
|
||||
void Handle_OP_Split(const EQApplicationPacket *app);
|
||||
void Handle_OP_SenseTraps(const EQApplicationPacket *app);
|
||||
void Handle_OP_DisarmTraps(const EQApplicationPacket *app);
|
||||
void Handle_OP_OpenTributeMaster(const EQApplicationPacket *app);
|
||||
void Handle_OP_OpenGuildTributeMaster(const EQApplicationPacket *app);
|
||||
void Handle_OP_TributeItem(const EQApplicationPacket *app);
|
||||
void Handle_OP_TributeMoney(const EQApplicationPacket *app);
|
||||
void Handle_OP_SelectTribute(const EQApplicationPacket *app);
|
||||
void Handle_OP_TributeUpdate(const EQApplicationPacket *app);
|
||||
void Handle_OP_TributeToggle(const EQApplicationPacket *app);
|
||||
void Handle_OP_TributeNPC(const EQApplicationPacket *app);
|
||||
void Handle_OP_ConfirmDelete(const EQApplicationPacket *app);
|
||||
void Handle_OP_CrashDump(const EQApplicationPacket *app);
|
||||
void Handle_OP_ControlBoat(const EQApplicationPacket *app);
|
||||
void Handle_OP_DumpName(const EQApplicationPacket *app);
|
||||
void Handle_OP_SetRunMode(const EQApplicationPacket *app);
|
||||
void Handle_OP_SafeFallSuccess(const EQApplicationPacket *app);
|
||||
void Handle_OP_Heartbeat(const EQApplicationPacket *app);
|
||||
void Handle_OP_SafePoint(const EQApplicationPacket *app);
|
||||
void Handle_OP_FindPersonRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_BankerChange(const EQApplicationPacket *app);
|
||||
void Handle_OP_LeadershipExpToggle(const EQApplicationPacket *app);
|
||||
void Handle_OP_SetTitle(const EQApplicationPacket *app);
|
||||
void Handle_OP_RequestTitles(const EQApplicationPacket *app);
|
||||
void Handle_OP_PurchaseLeadershipAA(const EQApplicationPacket *app);
|
||||
void Handle_OP_Ignore(const EQApplicationPacket *app);
|
||||
void Handle_OP_LoadSpellSet(const EQApplicationPacket *app);
|
||||
void Handle_OP_AutoFire(const EQApplicationPacket *app);
|
||||
void Handle_OP_Rewind(const EQApplicationPacket *app);
|
||||
void Handle_OP_RaidCommand(const EQApplicationPacket *app);
|
||||
void Handle_OP_Translocate(const EQApplicationPacket *app);
|
||||
void Handle_OP_Sacrifice(const EQApplicationPacket *app);
|
||||
void Handle_OP_AcceptNewTask(const EQApplicationPacket *app);
|
||||
void Handle_OP_CancelTask(const EQApplicationPacket *app);
|
||||
void Handle_OP_TaskHistoryRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_KeyRing(const EQApplicationPacket *app);
|
||||
void Handle_OP_FriendsWho(const EQApplicationPacket *app);
|
||||
void Handle_OP_Bandolier(const EQApplicationPacket *app);
|
||||
void Handle_OP_PopupResponse(const EQApplicationPacket *app);
|
||||
void Handle_OP_PotionBelt(const EQApplicationPacket *app);
|
||||
void Handle_OP_LFGGetMatchesRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_LFPCommand(const EQApplicationPacket *app);
|
||||
void Handle_OP_LFPGetMatchesRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_Barter(const EQApplicationPacket *app);
|
||||
void Handle_OP_VoiceMacroIn(const EQApplicationPacket *app);
|
||||
void Handle_OP_DoGroupLeadershipAbility(const EQApplicationPacket *app);
|
||||
void Handle_OP_ClearNPCMarks(const EQApplicationPacket *app);
|
||||
void Handle_OP_DelegateAbility(const EQApplicationPacket *app);
|
||||
void Handle_OP_ApplyPoison(const EQApplicationPacket *app);
|
||||
void Handle_OP_AugmentInfo(const EQApplicationPacket *app);
|
||||
void Handle_OP_PVPLeaderBoardRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_PVPLeaderBoardDetailsRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_AdventureMerchantSell(const EQApplicationPacket *app);
|
||||
void Handle_OP_AdventureStatsRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_AdventureLeaderboardRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_RespawnWindow(const EQApplicationPacket *app);
|
||||
void Handle_OP_GroupUpdate(const EQApplicationPacket *app);
|
||||
void Handle_OP_SetStartCity(const EQApplicationPacket *app);
|
||||
void Handle_OP_Report(const EQApplicationPacket *app);
|
||||
void Handle_OP_VetClaimRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_GMSearchCorpse(const EQApplicationPacket *app);
|
||||
void Handle_OP_GuildBank(const EQApplicationPacket *app);
|
||||
void Handle_OP_GroupRoles(const EQApplicationPacket *app);
|
||||
void Handle_OP_HideCorpse(const EQApplicationPacket *app);
|
||||
void Handle_OP_TradeBusy(const EQApplicationPacket *app);
|
||||
void Handle_OP_GuildUpdateURLAndChannel(const EQApplicationPacket *app);
|
||||
void Handle_OP_GuildStatus(const EQApplicationPacket *app);
|
||||
void Handle_OP_BlockedBuffs(const EQApplicationPacket *app);
|
||||
void Handle_OP_RemoveBlockedBuffs(const EQApplicationPacket *app);
|
||||
void Handle_OP_ClearBlockedBuffs(const EQApplicationPacket *app);
|
||||
void Handle_OP_BuffRemoveRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_CorpseDrag(const EQApplicationPacket *app);
|
||||
void Handle_OP_CorpseDrop(const EQApplicationPacket *app);
|
||||
void Handle_OP_GroupMakeLeader(const EQApplicationPacket *app);
|
||||
void Handle_OP_GuildCreate(const EQApplicationPacket *app);
|
||||
void Handle_OP_AltCurrencyMerchantRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_AltCurrencySellSelection(const EQApplicationPacket *app);
|
||||
void Handle_OP_AltCurrencyPurchase(const EQApplicationPacket *app);
|
||||
void Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app);
|
||||
void Handle_OP_AltCurrencySell(const EQApplicationPacket *app);
|
||||
void Handle_OP_CrystalReclaim(const EQApplicationPacket *app);
|
||||
void Handle_OP_CrystalCreate(const EQApplicationPacket *app);
|
||||
void Handle_OP_LFGuild(const EQApplicationPacket *app);
|
||||
void Handle_OP_XTargetRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_XTargetAutoAddHaters(const EQApplicationPacket *app);
|
||||
void Handle_OP_ItemPreview(const EQApplicationPacket *app);
|
||||
void Handle_OP_MercenaryDataRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_MercenaryHire(const EQApplicationPacket *app);
|
||||
void Handle_OP_MercenaryCommand(const EQApplicationPacket *app);
|
||||
void Handle_OP_MercenaryDataUpdateRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_MercenarySuspendRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_MercenaryDismiss(const EQApplicationPacket *app);
|
||||
void Handle_OP_MercenaryTimerRequest(const EQApplicationPacket *app);
|
||||
void Handle_OP_OpenInventory(const EQApplicationPacket *app);
|
||||
void Handle_OP_OpenContainer(const EQApplicationPacket *app);
|
||||
File diff suppressed because it is too large
Load Diff
+11659
File diff suppressed because it is too large
Load Diff
+351
@@ -0,0 +1,351 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef COMMAND_H
|
||||
#define COMMAND_H
|
||||
|
||||
#include "../common/seperator.h"
|
||||
#include "../common/EQStream.h"
|
||||
#include "client.h"
|
||||
|
||||
#define COMMAND_CHAR '#'
|
||||
#define CMDALIASES 5
|
||||
|
||||
typedef void (*CmdFuncPtr)(Client *,const Seperator *);
|
||||
|
||||
// this is a command list item
|
||||
/*struct cl_struct
|
||||
{
|
||||
char *command[CMDALIASES]; // the command(s)
|
||||
char *desc; // description of command
|
||||
CmdFuncPtr function; // the function to call
|
||||
int access; // the required 'status' level
|
||||
|
||||
struct cl_struct *next; // linked list
|
||||
};
|
||||
|
||||
extern struct cl_struct *commandlist; // the head of the list
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
const char *command[CMDALIASES]; // the command(s)
|
||||
int access;
|
||||
const char *desc; // description of command
|
||||
CmdFuncPtr function; //null means perl function
|
||||
} CommandRecord;
|
||||
|
||||
extern int (*command_dispatch)(Client *,char const*);
|
||||
extern int commandcount; // number of commands loaded
|
||||
|
||||
// the command system:
|
||||
int command_init(void);
|
||||
void command_deinit(void);
|
||||
int command_add(const char *command_string, const char *desc, int access, CmdFuncPtr function);
|
||||
int command_notavail(Client *c, const char *message);
|
||||
int command_realdispatch(Client *c, char const *message);
|
||||
void command_logcommand(Client *c, const char *message);
|
||||
int command_add_perl(const char *command_string, const char *desc, int access);
|
||||
void command_clear_perl();
|
||||
|
||||
//commands
|
||||
void command_resetaa(Client* c,const Seperator *sep);
|
||||
void command_bind(Client* c,const Seperator *sep);
|
||||
void command_sendop(Client *c, const Seperator *sep);
|
||||
void command_optest(Client *c, const Seperator *sep);
|
||||
void command_setstat(Client *c, const Seperator *sep);
|
||||
void command_incstat(Client *c, const Seperator *sep);
|
||||
void command_help(Client *c, const Seperator *sep);
|
||||
void command_version(Client *c, const Seperator *sep);
|
||||
void command_eitem(Client *c, const Seperator *sep);
|
||||
void command_setfaction(Client *c, const Seperator *sep);
|
||||
void command_serversidename(Client *c, const Seperator *sep);
|
||||
void command_testspawnkill(Client *c, const Seperator *sep);
|
||||
void command_testspawn(Client *c, const Seperator *sep);
|
||||
void command_wc(Client *c, const Seperator *sep);
|
||||
void command_numauths(Client *c, const Seperator *sep);
|
||||
void command_setanim(Client *c, const Seperator *sep);
|
||||
void command_connectworldserver(Client *c, const Seperator *sep);
|
||||
void command_serverinfo(Client *c, const Seperator *sep);
|
||||
void command_crashtest(Client *c, const Seperator *sep);
|
||||
void command_getvariable(Client *c, const Seperator *sep);
|
||||
void command_chat(Client *c, const Seperator *sep);
|
||||
void command_showpetspell(Client *c, const Seperator *sep);
|
||||
void command_ipc(Client *c, const Seperator *sep);
|
||||
void command_npcloot(Client *c, const Seperator *sep);
|
||||
void command_log(Client *c, const Seperator *sep);
|
||||
void command_gm(Client *c, const Seperator *sep);
|
||||
void command_summon(Client *c, const Seperator *sep);
|
||||
void command_zone(Client *c, const Seperator *sep);
|
||||
void command_zone_instance(Client *c, const Seperator *sep);
|
||||
void command_peqzone(Client *c, const Seperator *sep);
|
||||
void command_showbuffs(Client *c, const Seperator *sep);
|
||||
void command_movechar(Client *c, const Seperator *sep);
|
||||
void command_viewpetition(Client *c, const Seperator *sep);
|
||||
void command_petitioninfo(Client *c, const Seperator *sep);
|
||||
void command_delpetition(Client *c, const Seperator *sep);
|
||||
void command_listnpcs(Client *c, const Seperator *sep);
|
||||
void command_date(Client *c, const Seperator *sep);
|
||||
void command_timezone(Client *c, const Seperator *sep);
|
||||
void command_synctod(Client *c, const Seperator *sep);
|
||||
void command_invul(Client *c, const Seperator *sep);
|
||||
void command_hideme(Client *c, const Seperator *sep);
|
||||
void command_emote(Client *c, const Seperator *sep);
|
||||
void command_fov(Client *c, const Seperator *sep);
|
||||
void command_manastat(Client *c, const Seperator *sep);
|
||||
void command_npcstats(Client *c, const Seperator *sep);
|
||||
void command_zclip(Client *c, const Seperator *sep);
|
||||
void command_npccast(Client *c, const Seperator *sep);
|
||||
void command_zstats(Client *c, const Seperator *sep);
|
||||
void command_permaclass(Client *c, const Seperator *sep);
|
||||
void command_permarace(Client *c, const Seperator *sep);
|
||||
void command_permagender(Client *c, const Seperator *sep);
|
||||
void command_weather(Client *c, const Seperator *sep);
|
||||
void command_zheader(Client *c, const Seperator *sep);
|
||||
void command_zsky(Client *c, const Seperator *sep);
|
||||
void command_zcolor(Client *c, const Seperator *sep);
|
||||
void command_spon(Client *c, const Seperator *sep);
|
||||
void command_spoff(Client *c, const Seperator *sep);
|
||||
void command_itemtest(Client *c, const Seperator *sep);
|
||||
void command_gassign(Client *c, const Seperator *sep);
|
||||
void command_setitemstatus(Client *c, const Seperator *sep);
|
||||
void command_ai(Client *c, const Seperator *sep);
|
||||
void command_worldshutdown(Client *c, const Seperator *sep);
|
||||
void command_sendzonespawns(Client *c, const Seperator *sep);
|
||||
void command_zsave(Client *c, const Seperator *sep);
|
||||
void command_dbspawn2(Client *c, const Seperator *sep);
|
||||
void command_copychar(Client *c, const Seperator *sep);
|
||||
void command_shutdown(Client *c, const Seperator *sep);
|
||||
void command_delacct(Client *c, const Seperator *sep);
|
||||
void command_setpass(Client *c, const Seperator *sep);
|
||||
void command_setlsinfo(Client *c, const Seperator *sep);
|
||||
void command_grid(Client *c, const Seperator *sep);
|
||||
void command_wp(Client *c, const Seperator *sep);
|
||||
void command_iplookup(Client *c, const Seperator *sep);
|
||||
void command_size(Client *c, const Seperator *sep);
|
||||
void command_mana(Client *c, const Seperator *sep);
|
||||
void command_flymode(Client *c, const Seperator *sep);
|
||||
void command_showskills(Client *c, const Seperator *sep);
|
||||
void command_findspell(Client *c, const Seperator *sep);
|
||||
void command_castspell(Client *c, const Seperator *sep);
|
||||
void command_setlanguage(Client *c, const Seperator *sep);
|
||||
void command_setskill(Client *c, const Seperator *sep);
|
||||
void command_setskillall(Client *c, const Seperator *sep);
|
||||
void command_race(Client *c, const Seperator *sep);
|
||||
void command_gender(Client *c, const Seperator *sep);
|
||||
void command_makepet(Client *c, const Seperator *sep);
|
||||
void command_level(Client *c, const Seperator *sep);
|
||||
void command_spawn(Client *c, const Seperator *sep);
|
||||
void command_texture(Client *c, const Seperator *sep);
|
||||
void command_npctypespawn(Client *c, const Seperator *sep);
|
||||
void command_heal(Client *c, const Seperator *sep);
|
||||
void command_appearance(Client *c, const Seperator *sep);
|
||||
void command_charbackup(Client *c, const Seperator *sep);
|
||||
void command_nukeitem(Client *c, const Seperator *sep);
|
||||
void command_peekinv(Client *c, const Seperator *sep);
|
||||
void command_findnpctype(Client *c, const Seperator *sep);
|
||||
void command_findzone(Client *c, const Seperator *sep);
|
||||
void command_viewnpctype(Client *c, const Seperator *sep);
|
||||
void command_reloadqst(Client *c, const Seperator *sep);
|
||||
void command_reloadworld(Client *c, const Seperator *sep);
|
||||
void command_reloadzps(Client *c, const Seperator *sep);
|
||||
void command_zoneshutdown(Client *c, const Seperator *sep);
|
||||
void command_zonebootup(Client *c, const Seperator *sep);
|
||||
void command_kick(Client *c, const Seperator *sep);
|
||||
void command_attack(Client *c, const Seperator *sep);
|
||||
void command_lock(Client *c, const Seperator *sep);
|
||||
void command_unlock(Client *c, const Seperator *sep);
|
||||
void command_motd(Client *c, const Seperator *sep);
|
||||
void command_listpetition(Client *c, const Seperator *sep);
|
||||
void command_equipitem(Client *c, const Seperator *sep);
|
||||
void command_zonelock(Client *c, const Seperator *sep);
|
||||
void command_corpse(Client *c, const Seperator *sep);
|
||||
void command_fixmob(Client *c, const Seperator *sep);
|
||||
void command_gmspeed(Client *c, const Seperator *sep);
|
||||
void command_title(Client *c, const Seperator *sep);
|
||||
void command_titlesuffix(Client *c, const Seperator *sep);
|
||||
void command_spellinfo(Client *c, const Seperator *sep);
|
||||
void command_lastname(Client *c, const Seperator *sep);
|
||||
void command_memspell(Client *c, const Seperator *sep);
|
||||
void command_save(Client *c, const Seperator *sep);
|
||||
void command_showstats(Client *c, const Seperator *sep);
|
||||
void command_mystats(Client *c, const Seperator *sep);
|
||||
void command_myskills(Client *c, const Seperator *sep);
|
||||
void command_depop(Client *c, const Seperator *sep);
|
||||
void command_depopzone(Client *c, const Seperator *sep);
|
||||
void command_repop(Client *c, const Seperator *sep);
|
||||
void command_spawnstatus(Client *c, const Seperator *sep);
|
||||
void command_nukebuffs(Client *c, const Seperator *sep);
|
||||
void command_zuwcoords(Client *c, const Seperator *sep);
|
||||
void command_zunderworld(Client *c, const Seperator *sep);
|
||||
void command_zsafecoords(Client *c, const Seperator *sep);
|
||||
void command_freeze(Client *c, const Seperator *sep);
|
||||
void command_unfreeze(Client *c, const Seperator *sep);
|
||||
void command_pvp(Client *c, const Seperator *sep);
|
||||
void command_setxp(Client *c, const Seperator *sep);
|
||||
void command_setpvppoints(Client *c, const Seperator *sep);
|
||||
void command_name(Client *c, const Seperator *sep);
|
||||
void command_tempname(Client *c, const Seperator *sep);
|
||||
void command_npcspecialattk(Client *c, const Seperator *sep);
|
||||
void command_kill(Client *c, const Seperator *sep);
|
||||
void command_haste(Client *c, const Seperator *sep);
|
||||
void command_damage(Client *c, const Seperator *sep);
|
||||
void command_zonespawn(Client *c, const Seperator *sep);
|
||||
void command_npcspawn(Client *c, const Seperator *sep);
|
||||
void command_spawnfix(Client *c, const Seperator *sep);
|
||||
void command_loc(Client *c, const Seperator *sep);
|
||||
void command_goto(Client *c, const Seperator *sep);
|
||||
#ifdef BUGTRACK
|
||||
void command_bug(Client *c, const Seperator *sep);
|
||||
#endif
|
||||
void command_iteminfo(Client *c, const Seperator *sep);
|
||||
void command_uptime(Client *c, const Seperator *sep);
|
||||
void command_flag(Client *c, const Seperator *sep);
|
||||
void command_time(Client *c, const Seperator *sep);
|
||||
void command_guild(Client *c, const Seperator *sep);
|
||||
bool helper_guild_edit(Client *c, uint32 dbid, uint32 eqid, uint8 rank, const char* what, const char* value);
|
||||
void command_zonestatus(Client *c, const Seperator *sep);
|
||||
void command_manaburn(Client *c, const Seperator *sep);
|
||||
void command_viewmessage(Client *c, const Seperator *sep);
|
||||
void command_doanim(Client *c, const Seperator *sep);
|
||||
void command_randomfeatures(Client *c, const Seperator *sep);
|
||||
void command_face(Client *c, const Seperator *sep);
|
||||
void command_helm(Client *c, const Seperator *sep);
|
||||
void command_hair(Client *c, const Seperator *sep);
|
||||
void command_haircolor(Client *c, const Seperator *sep);
|
||||
void command_beard(Client *c, const Seperator *sep);
|
||||
void command_beardcolor(Client *c, const Seperator *sep);
|
||||
void command_tattoo(Client *c, const Seperator *sep);
|
||||
void command_heritage(Client *c, const Seperator *sep);
|
||||
void command_details(Client *c, const Seperator *sep);
|
||||
void command_scribespells(Client *c, const Seperator *sep);
|
||||
void command_unscribespells(Client *c, const Seperator *sep);
|
||||
void command_wpinfo(Client *c, const Seperator *sep);
|
||||
void command_wpadd(Client *c, const Seperator *sep);
|
||||
void command_interrupt(Client *c, const Seperator *sep);
|
||||
void command_d1(Client *c, const Seperator *sep);
|
||||
void command_summonitem(Client *c, const Seperator *sep);
|
||||
void command_giveitem(Client *c, const Seperator *sep);
|
||||
void command_givemoney(Client *c, const Seperator *sep);
|
||||
void command_itemsearch(Client *c, const Seperator *sep);
|
||||
void command_datarate(Client *c, const Seperator *sep);
|
||||
void command_setaaxp(Client *c, const Seperator *sep);
|
||||
void command_setaapts(Client *c, const Seperator *sep);
|
||||
void command_setcrystals(Client *c, const Seperator *sep);
|
||||
void command_stun(Client *c, const Seperator *sep);
|
||||
void command_ban(Client *c, const Seperator *sep);
|
||||
void command_suspend(Client *c, const Seperator *sep);
|
||||
void command_ipban(Client *c, const Seperator *sep);
|
||||
void command_oocmute(Client *c, const Seperator *sep);
|
||||
void command_revoke(Client *c, const Seperator *sep);
|
||||
void command_checklos(Client *c, const Seperator *sep);
|
||||
void command_set_adventure_points(Client *c, const Seperator *sep);
|
||||
void command_npcsay(Client *c, const Seperator *sep);
|
||||
void command_npcshout(Client *c, const Seperator *sep);
|
||||
void command_npcemote(Client *c, const Seperator *sep);
|
||||
void command_npcedit(Client *c, const Seperator *sep);
|
||||
void command_timers(Client *c, const Seperator *sep);
|
||||
void command_undye(Client *c, const Seperator *sep);
|
||||
void command_undyeme(Client *c, const Seperator *sep);
|
||||
void command_hp(Client *c, const Seperator *sep);
|
||||
void command_ginfo(Client *c, const Seperator *sep);
|
||||
void command_logs(Client *c, const Seperator *sep);
|
||||
void command_nologs(Client *c, const Seperator *sep);
|
||||
void command_logsql(Client *c, const Seperator *sep);
|
||||
void command_qglobal(Client *c, const Seperator *sep);
|
||||
void command_fear(Client *c, const Seperator *sep);
|
||||
void command_path(Client *c, const Seperator *sep);
|
||||
void command_ginfo(Client *c, const Seperator *sep);
|
||||
void command_opcode(Client *c, const Seperator *sep);
|
||||
void command_aggro(Client *c, const Seperator *sep);
|
||||
void command_hatelist(Client *c, const Seperator *sep);
|
||||
void command_aggrozone(Client *c, const Seperator *sep);
|
||||
void command_reloadstatic(Client *c, const Seperator *sep);
|
||||
void command_flags(Client *c, const Seperator *sep);
|
||||
void command_flagedit(Client *c, const Seperator *sep);
|
||||
void command_mlog(Client *c, const Seperator *sep);
|
||||
void command_serverrules(Client *c, const Seperator *sep);
|
||||
void command_acceptrules(Client *c, const Seperator *sep);
|
||||
void command_guildcreate(Client *c, const Seperator *sep);
|
||||
void command_guildapprove(Client *c, const Seperator *sep);
|
||||
void command_guildlist(Client *c, const Seperator *sep);
|
||||
void command_rules(Client *c, const Seperator *sep);
|
||||
void command_task(Client *c, const Seperator *sep);
|
||||
void command_reloadtitles(Client *c, const Seperator *sep);
|
||||
void command_altactivate(Client *c, const Seperator *sep);
|
||||
void command_refundaa(Client *c, const Seperator *sep);
|
||||
void command_traindisc(Client *c, const Seperator *sep);
|
||||
void command_deletegraveyard(Client *c, const Seperator *sep);
|
||||
void command_setgraveyard(Client *c, const Seperator *sep);
|
||||
void command_getplayerburriedcorpsecount(Client *c, const Seperator *sep);
|
||||
void command_summonburriedplayercorpse(Client *c, const Seperator *sep);
|
||||
void command_unscribespell(Client *c, const Seperator *sep);
|
||||
void command_scribespell(Client *c, const Seperator *sep);
|
||||
void command_refreshgroup(Client *c, const Seperator *sep);
|
||||
void command_advnpcspawn(Client *c, const Seperator *sep);
|
||||
void command_modifynpcstat(Client *c, const Seperator *sep);
|
||||
void command_instance(Client *c, const Seperator *sep);
|
||||
void command_setstartzone(Client *c, const Seperator *sep);
|
||||
void command_netstats(Client *c, const Seperator *sep);
|
||||
void command_object(Client* c, const Seperator *sep);
|
||||
void command_raidloot(Client* c, const Seperator *sep);
|
||||
void command_globalview(Client* c, const Seperator *sep);
|
||||
void command_emoteview(Client* c, const Seperator *sep);
|
||||
void command_reloademote(Client* c, const Seperator *sep);
|
||||
void command_emotesearch(Client* c, const Seperator *sep);
|
||||
void command_distance(Client *c, const Seperator *sep);
|
||||
void command_cvs(Client *c, const Seperator *sep);
|
||||
void command_max_all_skills(Client *c, const Seperator *sep);
|
||||
void command_showbonusstats(Client *c, const Seperator *sep);
|
||||
void command_reloadallrules(Client *c, const Seperator *sep);
|
||||
void command_reloadworldrules(Client *c, const Seperator *sep);
|
||||
void command_reloadlevelmods(Client *c, const Seperator *sep);
|
||||
void command_camerashake(Client *c, const Seperator *sep);
|
||||
void command_disarmtrap(Client *c, const Seperator *sep);
|
||||
void command_sensetrap(Client *c, const Seperator *sep);
|
||||
void command_picklock(Client *c, const Seperator *sep);
|
||||
void command_qtest(Client *c, const Seperator *sep);
|
||||
void command_mysql(Client *c, const Seperator *sep);
|
||||
void command_xtargets(Client *c, const Seperator *sep);
|
||||
void command_printquestitems(Client *c, const Seperator *sep);
|
||||
void command_clearquestitems(Client *c, const Seperator *sep);
|
||||
void command_zopp(Client *c, const Seperator *sep);
|
||||
void command_augmentitem(Client *c, const Seperator *sep);
|
||||
|
||||
#ifdef EMBPERL
|
||||
void command_embperl_plugin(Client *c, const Seperator *sep);
|
||||
void command_embperl_eval(Client *c, const Seperator *sep);
|
||||
void command_reloadpl(Client *c, const Seperator *sep);
|
||||
#endif
|
||||
|
||||
#ifdef EQPROFILE
|
||||
void command_profiledump(Client *c, const Seperator *sep);
|
||||
void command_profilereset(Client *c, const Seperator *sep);
|
||||
#endif
|
||||
|
||||
#ifdef PACKET_PROFILER
|
||||
void command_packetprofile(Client *c, const Seperator *sep);
|
||||
#endif
|
||||
|
||||
#ifdef BOTS
|
||||
#include "bot.h"
|
||||
void command_bot(Client*c, const Seperator *sep);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
+486
@@ -0,0 +1,486 @@
|
||||
#ifndef __EQEMU_ZONE_COMMON_H
|
||||
#define __EQEMU_ZONE_COMMON_H
|
||||
|
||||
#include "../common/types.h"
|
||||
#include "spdat.h"
|
||||
|
||||
#define HIGHEST_RESIST 9 //Max resist type value
|
||||
|
||||
/* solar: macros for IsAttackAllowed, IsBeneficialAllowed */
|
||||
#define _CLIENT(x) (x && x->IsClient() && !x->CastToClient()->IsBecomeNPC())
|
||||
#define _NPC(x) (x && x->IsNPC() && !x->CastToMob()->GetOwnerID())
|
||||
#define _BECOMENPC(x) (x && x->IsClient() && x->CastToClient()->IsBecomeNPC())
|
||||
#define _CLIENTCORPSE(x) (x && x->IsCorpse() && x->CastToCorpse()->IsPlayerCorpse() && !x->CastToCorpse()->IsBecomeNPCCorpse())
|
||||
#define _NPCCORPSE(x) (x && x->IsCorpse() && (x->CastToCorpse()->IsNPCCorpse() || x->CastToCorpse()->IsBecomeNPCCorpse()))
|
||||
#define _CLIENTPET(x) (x && x->CastToMob()->GetOwner() && x->CastToMob()->GetOwner()->IsClient())
|
||||
#define _NPCPET(x) (x && x->IsNPC() && x->CastToMob()->GetOwner() && x->CastToMob()->GetOwner()->IsNPC())
|
||||
#define _BECOMENPCPET(x) (x && x->CastToMob()->GetOwner() && x->CastToMob()->GetOwner()->IsClient() && x->CastToMob()->GetOwner()->CastToClient()->IsBecomeNPC())
|
||||
|
||||
|
||||
//LOS Parameters:
|
||||
#define HEAD_POSITION 0.9f //ratio of GetSize() where NPCs see from
|
||||
#define SEE_POSITION 0.5f //ratio of GetSize() where NPCs try to see for LOS
|
||||
#define CHECK_LOS_STEP 1.0f
|
||||
|
||||
#define MAX_SHIELDERS 2 //I dont know if this is based on a client limit
|
||||
|
||||
#define ARCHETYPE_HYBRID 1
|
||||
#define ARCHETYPE_CASTER 2
|
||||
#define ARCHETYPE_MELEE 3
|
||||
|
||||
#define CON_GREEN 2
|
||||
#define CON_LIGHTBLUE 18
|
||||
#define CON_BLUE 4
|
||||
#define CON_WHITE 20
|
||||
#define CON_YELLOW 15
|
||||
#define CON_RED 13
|
||||
|
||||
//Spell specialization parameters, not sure of a better place for them
|
||||
#define SPECIALIZE_FIZZLE 11 //% fizzle chance reduce at 200 specialized
|
||||
#define SPECIALIZE_MANA_REDUCE 12 //% mana cost reduction at 200 specialized
|
||||
|
||||
//these are large right now because the x,y,z coords of the zone
|
||||
//lines do not make a lot of sense
|
||||
//Maximum distance from a zone point given that the request didnt
|
||||
//know what zone that the line was for
|
||||
#define ZONEPOINT_NOZONE_RANGE 40000.0f
|
||||
//Maximum distance from a zone point if zone was specified
|
||||
#define ZONEPOINT_ZONE_RANGE 40000.0f
|
||||
|
||||
typedef enum { //focus types
|
||||
focusSpellHaste = 1,
|
||||
focusSpellDuration,
|
||||
focusRange,
|
||||
focusReagentCost,
|
||||
focusManaCost,
|
||||
focusImprovedHeal,
|
||||
focusImprovedDamage,
|
||||
focusImprovedDOT, //i dont know about this...
|
||||
focusImprovedDamage2,
|
||||
focusImprovedUndeadDamage,
|
||||
focusPetPower,
|
||||
focusResistRate,
|
||||
focusSpellHateMod,
|
||||
focusTriggerOnCast,
|
||||
focusSpellVulnerability,
|
||||
focusTwincast,
|
||||
focusSympatheticProc,
|
||||
focusSpellDamage,
|
||||
focusFF_Damage_Amount,
|
||||
focusSpellDurByTic,
|
||||
focusSwarmPetDuration,
|
||||
focusReduceRecastTime,
|
||||
focusBlockNextSpell,
|
||||
focusHealRate,
|
||||
focusAdditionalDamage,
|
||||
focusSpellEffectiveness,
|
||||
focusIncreaseNumHits,
|
||||
focusCriticalHealRate,
|
||||
focusAdditionalHeal2,
|
||||
focusAdditionalHeal,
|
||||
} focusType; //Any new FocusType needs to be added to the Mob::IsFocus function
|
||||
#define HIGHEST_FOCUS focusAdditionalHeal //Should always be last focusType in enum
|
||||
|
||||
|
||||
/*
|
||||
Used:
|
||||
b,d,f,g,j,m,n,o,p,r,t
|
||||
A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,Q,R,S,T,U,W,Y
|
||||
|
||||
Unused:
|
||||
a,c,e,h,k,l,q,s,u,v,w,x,y,z
|
||||
P,V,X
|
||||
*/
|
||||
|
||||
enum {
|
||||
SPECATK_NONE = 0,
|
||||
SPECATK_SUMMON, // S
|
||||
SPECATK_ENRAGE, // E
|
||||
SPECATK_RAMPAGE, // R
|
||||
SPECATK_AREA_RAMPAGE, // r
|
||||
SPECATK_FLURRY, // F
|
||||
SPECATK_TRIPLE, // T
|
||||
SPECATK_QUAD, // Q
|
||||
SPECATK_INNATE_DW, // L
|
||||
SPECATK_BANE, // b
|
||||
SPECATK_MAGICAL, // m
|
||||
SPECATK_RANGED_ATK, // Y
|
||||
UNSLOWABLE, // U
|
||||
UNMEZABLE, // M
|
||||
UNCHARMABLE, // C
|
||||
UNSTUNABLE, // N
|
||||
UNSNAREABLE, // I
|
||||
UNFEARABLE, // D
|
||||
UNDISPELLABLE, // K
|
||||
IMMUNE_MELEE, // A
|
||||
IMMUNE_MAGIC, // B
|
||||
IMMUNE_FLEEING, // f
|
||||
IMMUNE_MELEE_EXCEPT_BANE, // O
|
||||
IMMUNE_MELEE_NONMAGICAL, // W
|
||||
IMMUNE_AGGRO, // H - Won't aggro, ever.
|
||||
IMMUNE_AGGRO_ON, // G - Immune to being aggroed
|
||||
IMMUNE_CASTING_FROM_RANGE, // g
|
||||
IMMUNE_FEIGN_DEATH, // d
|
||||
IMMUNE_TAUNT, // i
|
||||
NPC_TUNNELVISION, // t
|
||||
NPC_NO_BUFFHEAL_FRIENDS, // n
|
||||
IMMUNE_PACIFY, // p
|
||||
LEASH, // J - Dispell, wipe agro && return to spawn
|
||||
TETHER, // j - Return to spawn
|
||||
DESTRUCTIBLE_OBJECT, // o - This is only for destructible objects
|
||||
NO_HARM_FROM_CLIENT, // Z - This is to prevent attacking NPC's period for clients
|
||||
SPECATK_MAXNUM
|
||||
};
|
||||
|
||||
typedef enum { //fear states
|
||||
fearStateNotFeared = 0,
|
||||
fearStateRunning, //I am running, hoping to find a grid at my WP
|
||||
fearStateRunningForever, //can run straight until spell ends
|
||||
fearStateGrid, //I am allready on a fear grid
|
||||
fearStateStuck //I cannot move somehow...
|
||||
} FearState;
|
||||
|
||||
enum { FlyMode0 = 0, FlyMode1 = 1, Flymode2 = 2, FlyMode3 = 3 };
|
||||
|
||||
struct TradeEntity;
|
||||
class Trade;
|
||||
enum TradeState {
|
||||
TradeNone,
|
||||
Trading,
|
||||
TradeAccepted,
|
||||
TradeCompleting
|
||||
};
|
||||
|
||||
//this is our internal representation of the BUFF struct, can put whatever we want in it
|
||||
struct Buffs_Struct {
|
||||
uint16 spellid;
|
||||
uint8 casterlevel;
|
||||
uint16 casterid; // Maybe change this to a pointer sometime, but gotta make sure it's 0'd when it no longer points to anything
|
||||
char caster_name[64];
|
||||
int32 ticsremaining;
|
||||
uint32 counters;
|
||||
uint32 numhits; //the number of physical hits this buff can take before it fades away, lots of druid armor spells take advantage of this mixed with powerful effects
|
||||
uint32 melee_rune;
|
||||
uint32 magic_rune;
|
||||
uint8 deathSaveSuccessChance;
|
||||
uint8 deathsaveCasterAARank;
|
||||
bool persistant_buff;
|
||||
bool client; //True if the caster is a client
|
||||
bool UpdateClient;
|
||||
};
|
||||
|
||||
struct StatBonuses {
|
||||
int16 AC;
|
||||
int32 HP;
|
||||
int32 HPRegen;
|
||||
int32 MaxHP;
|
||||
int32 ManaRegen;
|
||||
int32 EnduranceRegen;
|
||||
int32 Mana;
|
||||
int32 Endurance;
|
||||
int16 ATK;
|
||||
//would it be worth it to create a Stat_Struct?
|
||||
int16 STR;
|
||||
int16 STRCapMod;
|
||||
int16 HeroicSTR;
|
||||
int16 STA;
|
||||
int16 STACapMod;
|
||||
int16 HeroicSTA;
|
||||
int16 DEX;
|
||||
int16 DEXCapMod;
|
||||
int16 HeroicDEX;
|
||||
int16 AGI;
|
||||
int16 AGICapMod;
|
||||
int16 HeroicAGI;
|
||||
int16 INT;
|
||||
int16 INTCapMod;
|
||||
int16 HeroicINT;
|
||||
int16 WIS;
|
||||
int16 WISCapMod;
|
||||
int16 HeroicWIS;
|
||||
int16 CHA;
|
||||
int16 CHACapMod;
|
||||
int16 HeroicCHA;
|
||||
int16 MR;
|
||||
int16 MRCapMod;
|
||||
int16 HeroicMR;
|
||||
int16 FR;
|
||||
int16 FRCapMod;
|
||||
int16 HeroicFR;
|
||||
int16 CR;
|
||||
int16 CRCapMod;
|
||||
int16 HeroicCR;
|
||||
int16 PR;
|
||||
int16 PRCapMod;
|
||||
int16 HeroicPR;
|
||||
int16 DR;
|
||||
int16 DRCapMod;
|
||||
int16 HeroicDR;
|
||||
int16 Corrup;
|
||||
int16 CorrupCapMod;
|
||||
int16 HeroicCorrup;
|
||||
uint16 DamageShieldSpellID;
|
||||
int DamageShield; // this is damage done to mobs that attack this
|
||||
DmgShieldType DamageShieldType;
|
||||
int SpellDamageShield;
|
||||
int SpellShield;
|
||||
int ReverseDamageShield; // this is damage done to the mob when it attacks
|
||||
uint16 ReverseDamageShieldSpellID;
|
||||
DmgShieldType ReverseDamageShieldType;
|
||||
int movementspeed;
|
||||
int16 haste;
|
||||
int16 hastetype2;
|
||||
int16 hastetype3;
|
||||
int16 inhibitmelee;
|
||||
float AggroRange; // when calculate just replace original value with this
|
||||
float AssistRange;
|
||||
int16 skillmod[HIGHEST_SKILL+1];
|
||||
int effective_casting_level;
|
||||
int reflect_chance; // chance to reflect incoming spell
|
||||
uint16 singingMod;
|
||||
uint16 brassMod;
|
||||
uint16 percussionMod;
|
||||
uint16 windMod;
|
||||
uint16 stringedMod;
|
||||
int8 hatemod;
|
||||
int32 EnduranceReduction;
|
||||
|
||||
int16 StrikeThrough; // PoP: Strike Through %
|
||||
int16 MeleeMitigation; //i = Shielding
|
||||
int16 CriticalHitChance[HIGHEST_SKILL+2]; //i
|
||||
int16 CriticalSpellChance; //i
|
||||
int16 SpellCritDmgIncrease; //i
|
||||
int16 DotCritDmgIncrease; //i
|
||||
int16 CriticalHealChance; //i
|
||||
int16 CriticalHealOverTime; //i
|
||||
int16 CriticalDoTChance; //i
|
||||
int16 CrippBlowChance; //
|
||||
int16 AvoidMeleeChance; //AvoidMeleeChance/10 == % chance i = Avoidance
|
||||
int16 RiposteChance; //i
|
||||
int16 DodgeChance; //i
|
||||
int16 ParryChance; //i
|
||||
int16 DualWieldChance; //i
|
||||
int16 DoubleAttackChance; //i
|
||||
int16 TripleAttackChance; //i
|
||||
int16 ResistSpellChance; //i
|
||||
int16 ResistFearChance; //i
|
||||
bool Fearless; //i
|
||||
bool IsFeared; //i
|
||||
int16 StunResist; //i
|
||||
int16 MeleeSkillCheck; //i
|
||||
uint8 MeleeSkillCheckSkill;
|
||||
int16 HitChance; //HitChance/15 == % increase i = Accuracy (Item: Accuracy)
|
||||
int16 HitChanceEffect[HIGHEST_SKILL+2]; //Spell effect Chance to Hit, straight percent increase
|
||||
int16 DamageModifier[HIGHEST_SKILL+2]; //i
|
||||
int16 MinDamageModifier[HIGHEST_SKILL+2]; //i
|
||||
int16 ProcChance; // ProcChance/10 == % increase i = CombatEffects
|
||||
int16 ExtraAttackChance;
|
||||
int16 DoTShielding;
|
||||
int16 DivineSaveChance[2]; // Second Chance (base1 = chance, base2 = spell on trigger)
|
||||
uint16 DeathSave[4]; // Death Pact [0](value = 1 partial 2 = full) [1]=slot [2]=LvLimit [3]=HealAmt
|
||||
int16 FlurryChance;
|
||||
int16 Accuracy[HIGHEST_SKILL+2]; //Accuracy/15 == % increase [Spell Effect: Accuracy)
|
||||
int16 HundredHands; //extra haste, stacks with all other haste i
|
||||
int8 MeleeLifetap; //i
|
||||
int16 HealRate; // Spell effect that influences effectiveness of heals
|
||||
int16 MaxHPChange; // Spell Effect
|
||||
int16 SkillDmgTaken[HIGHEST_SKILL+2]; // All Skills + -1
|
||||
int32 HealAmt; // Item Effect
|
||||
int32 SpellDmg; // Item Effect
|
||||
int32 Clairvoyance; // Item Effect
|
||||
int16 DSMitigation; // Item Effect
|
||||
int16 DSMitigationOffHand; // Lowers damage shield from off hand attacks.
|
||||
uint32 SpellTriggers[MAX_SPELL_TRIGGER]; // Innate/Spell/Item Spells that trigger when you cast
|
||||
uint32 SpellOnKill[MAX_SPELL_TRIGGER*3]; // Chance to proc after killing a mob
|
||||
uint32 SpellOnDeath[MAX_SPELL_TRIGGER*2]; // Chance to have effect cast when you die
|
||||
int16 CritDmgMob[HIGHEST_SKILL+2]; // All Skills + -1
|
||||
int16 SkillReuseTime[HIGHEST_SKILL+1]; // Reduces skill timers
|
||||
int16 SkillDamageAmount[HIGHEST_SKILL+2]; // All Skills + -1
|
||||
int16 TwoHandBluntBlock; // chance to block when wielding two hand blunt weapon
|
||||
uint16 ItemManaRegenCap; // Increases the amount of mana you have can over the cap(aa effect)
|
||||
int16 GravityEffect; // Indictor of spell effect
|
||||
bool AntiGate; // spell effect that prevents gating
|
||||
bool MagicWeapon; // spell effect that makes weapon magical
|
||||
int16 IncreaseBlockChance; // overall block chance modifier
|
||||
uint16 PersistantCasting; // chance to continue casting through a stun
|
||||
int XPRateMod; //i
|
||||
int HPPercCap; //Spell effect that limits you to being healed/regening beyond a % of your max
|
||||
int ManaPercCap; // ^^
|
||||
int EndPercCap; // ^^
|
||||
bool BlockNextSpell; // Indicates whether the client can block a spell or not
|
||||
//uint16 BlockSpellEffect[EFFECT_COUNT]; // Prevents spells with certain effects from landing on you *no longer used
|
||||
bool ImmuneToFlee; // Bypass the fleeing flag
|
||||
uint16 VoiceGraft; // Stores the ID of the mob with which to talk through
|
||||
uint16 SpellProcChance; // chance to proc from sympathetic spell effects
|
||||
uint16 CharmBreakChance; // chance to break charm
|
||||
int16 SongRange; // increases range of beneficial bard songs
|
||||
uint16 HPToManaConvert; // Uses HP to cast spells at specific conversion
|
||||
uint16 FocusEffects[HIGHEST_FOCUS+1]; // Stores the focus effectid for each focustype you have.
|
||||
bool NegateEffects; // Check if you contain a buff with negate effect. (only spellbonuses)
|
||||
int16 SkillDamageAmount2[HIGHEST_SKILL+2]; // Adds skill specific damage
|
||||
uint16 NegateAttacks[2]; // 0 = bool HasEffect 1 = Buff Slot
|
||||
uint16 MitigateMeleeRune[2]; // 0 = Mitigation value 1 = Buff Slot
|
||||
uint16 MitigateSpellRune[2]; // 0 = Mitigation value 1 = Buff Slot
|
||||
uint16 ManaAbsorbPercentDamage[2]; // 0 = Mitigation value 1 = Buff Slot
|
||||
int16 ShieldBlock; // Chance to Shield Block
|
||||
int16 BlockBehind; // Chance to Block Behind (with our without shield)
|
||||
//bool AbsorbMagicAtt; // Magic Rune *Need to be implemented for NegateEffect
|
||||
//bool MeleeRune; // Melee Rune *Need to be implemented for NegateEffect
|
||||
|
||||
// AAs
|
||||
int8 Packrat; //weight reduction for items, 1 point = 10%
|
||||
uint8 BuffSlotIncrease; // Increases number of available buff slots
|
||||
uint16 DelayDeath; // how far below 0 hp you can go
|
||||
int8 BaseMovementSpeed; // Adjust base run speed, does not stack with other movement bonuses.
|
||||
uint8 IncreaseRunSpeedCap; // Increase max run speed above cap.
|
||||
int16 DoubleSpecialAttack; // Chance to to perform a double special attack (ie flying kick 2x)
|
||||
int16 SpecialAttackKBProc[2]; // Chance to to do a knockback from special attacks. (0 = chance 1 = Skill)
|
||||
uint8 FrontalStunResist; // Chance to resist a frontal stun
|
||||
int16 BindWound; // Increase amount of HP by percent.
|
||||
int16 MaxBindWound; // Increase max amount of HP you can bind wound.
|
||||
int16 ChannelChanceSpells; // Modify chance to channel a spell.
|
||||
int16 ChannelChanceItems; // Modify chance to channel a items.
|
||||
uint8 SeeInvis; // See Invs.
|
||||
uint8 TripleBackstab; // Chance to triple backstab
|
||||
bool FrontalBackstabMinDmg; // Allow frontal backstabs for min damage
|
||||
uint8 FrontalBackstabChance; // Chance to backstab from the front for full damage
|
||||
uint8 ConsumeProjectile; // Chance to not consume arrow.
|
||||
uint16 ArcheryDamageModifier; // Increase Archery Damage by percent
|
||||
bool SecondaryDmgInc; // Allow off hand weapon to recieve damage bonus.
|
||||
uint16 GiveDoubleAttack; // Allow classes to double attack with a specified chance.
|
||||
int16 SlayUndead[2]; // Allow classes to do extra damage verse undead.(base1 = rate, base2 = damage mod)
|
||||
int16 PetCriticalHit; // Allow pets to critical hit with % value.
|
||||
int16 PetAvoidance; // Pet avoidance chance.
|
||||
int16 CombatStability; // Melee damage mitigation.
|
||||
int16 GiveDoubleRiposte[3]; // 0=Regular Chance, 1=Skill Attack Chance, 2=Skill
|
||||
uint16 RaiseSkillCap[2]; // Raise a specific skill cap (1 = value, 2=skill)
|
||||
int16 Ambidexterity; // Increase chance to duel wield by adding bonus 'skill'.
|
||||
int16 PetMaxHP; // Increase the max hp of your pet.
|
||||
int16 PetFlurry; // Chance for pet to flurry.
|
||||
uint8 MasteryofPast; // Can not fizzle spells below this level specified in value.
|
||||
bool GivePetGroupTarget; // All pets to recieve group buffs. (Pet Affinity)
|
||||
int16 RootBreakChance; // Chance root will break;
|
||||
int16 UnfailingDivinity; // Improves chance that DI will fire + increase partial heal.
|
||||
int16 ItemHPRegenCap; // Increase item regen cap.
|
||||
int16 SEResist[MAX_RESISTABLE_EFFECTS*2]; // Resist chance by specific spell effects.
|
||||
int16 OffhandRiposteFail; // chance for opponent to fail riposte with offhand attack.
|
||||
int16 ItemATKCap; // Raise item attack cap
|
||||
int32 FinishingBlow[2]; // Chance to do a finishing blow for specified damage amount.
|
||||
uint16 FinishingBlowLvl[2]; // Sets max level an NPC can be affected by FB. (base1 = lv, base2= ???)
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16 spellID;
|
||||
uint16 chance;
|
||||
uint16 base_spellID;
|
||||
} tProc;
|
||||
|
||||
struct Shielders_Struct {
|
||||
uint32 shielder_id;
|
||||
uint16 shielder_bonus;
|
||||
};
|
||||
|
||||
//eventually turn this into a typedef and
|
||||
//make DoAnim take it instead of int, to enforce its use.
|
||||
enum { //type arguments to DoAnim
|
||||
animKick = 1,
|
||||
animPiercing = 2, //might be piercing?
|
||||
anim2HSlashing = 3,
|
||||
anim2HWeapon = 4,
|
||||
anim1HWeapon = 5,
|
||||
animDualWield = 6,
|
||||
animTailRake = 7, //slam & Dpunch too
|
||||
animHand2Hand = 8,
|
||||
animShootBow = 9,
|
||||
animRoundKick = 11,
|
||||
animSwarmAttack = 20, //dunno about this one..
|
||||
animFlyingKick = 45,
|
||||
animTigerClaw = 46,
|
||||
animEagleStrike = 47,
|
||||
|
||||
};
|
||||
|
||||
|
||||
typedef enum {
|
||||
petFamiliar, //only listens to /pet get lost
|
||||
petAnimation, //does not listen to any commands
|
||||
petOther,
|
||||
petCharmed,
|
||||
petNPCFollow,
|
||||
petHatelist //remain active as long something is on the hatelist. Don't listen to any commands
|
||||
} PetType;
|
||||
|
||||
typedef enum {
|
||||
SingleTarget, // causes effect to spell_target
|
||||
AETarget, // causes effect in aerange of target + target
|
||||
AECaster, // causes effect in aerange of 'this'
|
||||
GroupSpell, // causes effect to caster + target's group
|
||||
CAHateList, // causes effect to all people on caster's hate list within some range
|
||||
DirectionalAE,
|
||||
CastActUnknown
|
||||
} CastAction_type;
|
||||
|
||||
|
||||
struct MercType {
|
||||
uint32 Type;
|
||||
uint32 ClientVersion;
|
||||
};
|
||||
|
||||
struct MercData {
|
||||
uint32 MercTemplateID;
|
||||
uint32 MercType; // From dbstr_us.txt - Apprentice (330000100), Journeyman (330000200), Master (330000300)
|
||||
uint32 MercSubType; // From dbstr_us.txt - 330020105^23^Race: Guktan<br>Type: Healer<br>Confidence: High<br>Proficiency: Apprentice, Tier V...
|
||||
uint32 CostFormula; // To determine cost to client
|
||||
uint32 ClientVersion; // Only send valid mercs per expansion
|
||||
uint32 NPCID;
|
||||
};
|
||||
|
||||
class ItemInst;
|
||||
class Mob;
|
||||
// All data associated with a single trade
|
||||
class Trade
|
||||
{
|
||||
public:
|
||||
Trade(Mob* in_owner);
|
||||
virtual ~Trade();
|
||||
|
||||
void Reset();
|
||||
void SetTradeCash(uint32 in_pp, uint32 in_gp, uint32 in_sp, uint32 in_cp);
|
||||
|
||||
// Initiate a trade with another mob
|
||||
// Also puts other mob into trader mode with this mob
|
||||
void Start(uint32 mob_id, bool initiate_with=true);
|
||||
|
||||
// Mob the owner is trading with
|
||||
Mob* With();
|
||||
|
||||
// Add item from cursor slot to trade bucket (automatically does bag data too)
|
||||
void AddEntity(uint16 from_slot_id, uint16 trade_slot_id);
|
||||
|
||||
// Audit trade
|
||||
void LogTrade();
|
||||
|
||||
// Debug only method
|
||||
#if (EQDEBUG >= 9)
|
||||
void DumpTrade();
|
||||
#endif
|
||||
|
||||
public:
|
||||
// Object state
|
||||
TradeState state;
|
||||
int32 pp;
|
||||
int32 gp;
|
||||
int32 sp;
|
||||
int32 cp;
|
||||
|
||||
private:
|
||||
// Send item data for trade item to other person involved in trade
|
||||
void SendItemData(const ItemInst* inst, int16 dest_slot_id);
|
||||
|
||||
uint32 with_id;
|
||||
Mob* owner;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+823
@@ -0,0 +1,823 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "../common/debug.h"
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
using namespace std;
|
||||
#include "masterentity.h"
|
||||
#include "worldserver.h"
|
||||
#include "StringIDs.h"
|
||||
#include "zonedb.h"
|
||||
#include "../common/packet_functions.h"
|
||||
#include "../common/packet_dump.h"
|
||||
#include "../common/MiscFunctions.h"
|
||||
#include "guild_mgr.h"
|
||||
|
||||
#define OPEN_DOOR 0x02
|
||||
#define CLOSE_DOOR 0x03
|
||||
#define OPEN_INVDOOR 0x03
|
||||
#define CLOSE_INVDOOR 0x02
|
||||
|
||||
extern EntityList entity_list;
|
||||
extern WorldServer worldserver;
|
||||
|
||||
Doors::Doors(const Door* door)
|
||||
: close_timer(5000)
|
||||
{
|
||||
db_id = door->db_id;
|
||||
door_id = door->door_id;
|
||||
strn0cpy(zone_name,door->zone_name,32);
|
||||
strn0cpy(door_name,door->door_name,32);
|
||||
pos_x = door->pos_x;
|
||||
pos_y = door->pos_y;
|
||||
pos_z = door->pos_z;
|
||||
heading = door->heading;
|
||||
incline = door->incline;
|
||||
opentype = door->opentype;
|
||||
guild_id = door->guild_id;
|
||||
lockpick = door->lockpick;
|
||||
keyitem = door->keyitem;
|
||||
nokeyring = door->nokeyring;
|
||||
trigger_door = door->trigger_door;
|
||||
trigger_type = door->trigger_type;
|
||||
triggered=false;
|
||||
door_param = door->door_param;
|
||||
size = door->size;
|
||||
invert_state = door->invert_state;
|
||||
SetOpenState(false);
|
||||
|
||||
close_timer.Disable();
|
||||
|
||||
strn0cpy(dest_zone,door->dest_zone,32);
|
||||
dest_instance_id = door->dest_instance_id;
|
||||
dest_x = door->dest_x;
|
||||
dest_y = door->dest_y;
|
||||
dest_z = door->dest_z;
|
||||
dest_heading = door->dest_heading;
|
||||
|
||||
is_ldon_door = door->is_ldon_door;
|
||||
client_version_mask = door->client_version_mask;
|
||||
}
|
||||
|
||||
Doors::Doors(const char *dmodel, float dx, float dy, float dz, float dheading, uint8 dopentype, uint16 dsize)
|
||||
: close_timer(5000)
|
||||
{
|
||||
db_id = database.GetDoorsCountPlusOne(zone->GetShortName(), zone->GetInstanceVersion());
|
||||
door_id = database.GetDoorsDBCountPlusOne(zone->GetShortName(), zone->GetInstanceVersion());
|
||||
strn0cpy(zone_name,zone->GetShortName(),32);
|
||||
strn0cpy(door_name,dmodel,32);
|
||||
pos_x = dx;
|
||||
pos_y = dy;
|
||||
pos_z = dz;
|
||||
heading = dheading;
|
||||
incline = 0;
|
||||
opentype = dopentype;
|
||||
guild_id = 0;
|
||||
lockpick = 0;
|
||||
keyitem = 0;
|
||||
nokeyring = 0;
|
||||
trigger_door = 0;
|
||||
trigger_type = 0;
|
||||
triggered=false;
|
||||
door_param = 0;
|
||||
size = dsize;
|
||||
invert_state = 0;
|
||||
SetOpenState(false);
|
||||
|
||||
close_timer.Disable();
|
||||
|
||||
strn0cpy(dest_zone,"NONE",32);
|
||||
dest_instance_id = 0;
|
||||
dest_x = 0;
|
||||
dest_y = 0;
|
||||
dest_z = 0;
|
||||
dest_heading = 0;
|
||||
|
||||
is_ldon_door = 0;
|
||||
client_version_mask = 4294967295;
|
||||
}
|
||||
|
||||
|
||||
Doors::~Doors()
|
||||
{
|
||||
}
|
||||
|
||||
bool Doors::Process()
|
||||
{
|
||||
if(close_timer.Enabled() && close_timer.Check() && IsDoorOpen())
|
||||
{
|
||||
if (opentype == 40 || GetTriggerType() == 1)
|
||||
{
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct));
|
||||
MoveDoor_Struct* md = (MoveDoor_Struct*)outapp->pBuffer;
|
||||
md->doorid = door_id;
|
||||
md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR;
|
||||
entity_list.QueueClients(0, outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
triggered=false;
|
||||
close_timer.Disable();
|
||||
SetOpenState(false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Doors::HandleClick(Client* sender, uint8 trigger)
|
||||
{
|
||||
//door debugging info dump
|
||||
_log(DOORS__INFO, "%s clicked door %s (dbid %d, eqid %d) at (%.4f,%.4f,%.4f @%.4f)", sender->GetName(), door_name, db_id, door_id, pos_x, pos_y, pos_z, heading);
|
||||
_log(DOORS__INFO, " incline %d, opentype %d, lockpick %d, key %d, nokeyring %d, trigger %d type %d, param %d", incline, opentype, lockpick, keyitem, nokeyring, trigger_door, trigger_type, door_param);
|
||||
_log(DOORS__INFO, " size %d, invert %d, dest: %s (%.4f,%.4f,%.4f @%.4f)", size, invert_state, dest_zone, dest_x, dest_y, dest_z, dest_heading);
|
||||
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct));
|
||||
MoveDoor_Struct* md = (MoveDoor_Struct*)outapp->pBuffer;
|
||||
//DumpPacket(app);
|
||||
md->doorid = door_id;
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//used_pawn: Locked doors! Rogue friendly too =)
|
||||
//TODO: add check for other lockpick items
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
//TODO: ADVENTURE DOOR
|
||||
if(IsLDoNDoor())
|
||||
{
|
||||
if(sender)
|
||||
{
|
||||
if(RuleI(Adventure, ItemIDToEnablePorts) != 0)
|
||||
{
|
||||
if(!sender->KeyRingCheck(RuleI(Adventure, ItemIDToEnablePorts)))
|
||||
{
|
||||
if(sender->GetInv().HasItem(RuleI(Adventure, ItemIDToEnablePorts)) == SLOT_INVALID)
|
||||
{
|
||||
sender->Message_StringID(13, 5141);
|
||||
safe_delete(outapp);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
sender->KeyRingAdd(RuleI(Adventure, ItemIDToEnablePorts));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!sender->GetPendingAdventureDoorClick())
|
||||
{
|
||||
sender->PendingAdventureDoorClick();
|
||||
ServerPacket *pack = new ServerPacket(ServerOP_AdventureClickDoor, sizeof(ServerPlayerClickedAdventureDoor_Struct));
|
||||
ServerPlayerClickedAdventureDoor_Struct *ads = (ServerPlayerClickedAdventureDoor_Struct*)pack->pBuffer;
|
||||
strcpy(ads->player, sender->GetName());
|
||||
ads->zone_id = zone->GetZoneID();
|
||||
ads->id = GetDoorDBID();
|
||||
worldserver.SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 keyneeded = GetKeyItem();
|
||||
uint8 keepoffkeyring = GetNoKeyring();
|
||||
uint32 haskey = 0;
|
||||
uint32 playerkey = 0;
|
||||
const ItemInst *lockpicks = sender->GetInv().GetItem(SLOT_CURSOR);
|
||||
|
||||
haskey = sender->GetInv().HasItem(keyneeded, 1);
|
||||
|
||||
if(haskey != SLOT_INVALID)
|
||||
{
|
||||
playerkey = keyneeded;
|
||||
}
|
||||
|
||||
if(GetTriggerType() == 255)
|
||||
{ // this object isnt triggered
|
||||
if(trigger == 1)
|
||||
{ // this door is only triggered by an object
|
||||
if(!IsDoorOpen() || (opentype == 58))
|
||||
{
|
||||
md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
|
||||
}
|
||||
else
|
||||
{
|
||||
md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
safe_delete(outapp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// guild doors
|
||||
if(((keyneeded == 0) && (GetLockpick() == 0) && (guild_id == 0)) ||
|
||||
(IsDoorOpen() && (opentype == 58)) ||
|
||||
((guild_id > 0) && (guild_id == sender->GuildID())))
|
||||
{ //door not locked
|
||||
if(!IsDoorOpen() || (opentype == 58))
|
||||
{
|
||||
md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
|
||||
}
|
||||
else
|
||||
{
|
||||
md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // guild doors
|
||||
if((guild_id > 0) && !sender->GetGM())
|
||||
{
|
||||
string tmp;
|
||||
char tmpmsg[240]; // guild doors msgs
|
||||
if(guild_mgr.GetGuildNameByID(guild_id, tmp))
|
||||
{
|
||||
sprintf(tmpmsg, "Only members of the <%s> guild may enter here", tmp.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(tmpmsg, "Door is locked by an unknown guild");
|
||||
}
|
||||
sender->Message(4, tmpmsg);
|
||||
// safe_delete(outapp);
|
||||
// /\ possible missing line..all other 'fail' returns seem to have it
|
||||
return;
|
||||
}
|
||||
// a key is required or the door is locked but can be picked or both
|
||||
sender->Message(4, "This is locked..."); // debug spam - should probably go
|
||||
if(sender->GetGM()) // GM can always open locks - should probably be changed to require a key
|
||||
{
|
||||
sender->Message_StringID(4,DOORS_GM);
|
||||
if(!IsDoorOpen() || (opentype == 58))
|
||||
{
|
||||
md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
|
||||
}
|
||||
else
|
||||
{
|
||||
md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR;
|
||||
}
|
||||
}
|
||||
else if(playerkey)
|
||||
{ // they have something they are trying to open it with
|
||||
if(keyneeded && (keyneeded == playerkey))
|
||||
{ // key required and client is using the right key
|
||||
if(!keepoffkeyring)
|
||||
{
|
||||
sender->KeyRingAdd(playerkey);
|
||||
}
|
||||
sender->Message(4, "You got it open!");
|
||||
if(!IsDoorOpen() || (opentype == 58))
|
||||
{
|
||||
md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
|
||||
}
|
||||
else
|
||||
{
|
||||
md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(lockpicks != NULL)
|
||||
{
|
||||
if(sender->GetSkill(PICK_LOCK))
|
||||
{
|
||||
if(lockpicks->GetItem()->ItemType == ItemTypeLockPick)
|
||||
{
|
||||
float modskill=sender->GetSkill(PICK_LOCK);
|
||||
sender->CheckIncreaseSkill(PICK_LOCK, NULL, 1);
|
||||
|
||||
#if EQDEBUG>=5
|
||||
LogFile->write(EQEMuLog::Debug, "Client has lockpicks: skill=%f", modskill);
|
||||
#endif
|
||||
|
||||
if(GetLockpick() <= modskill)
|
||||
{
|
||||
if(!IsDoorOpen())
|
||||
{
|
||||
md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
|
||||
}
|
||||
else
|
||||
{
|
||||
md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR;
|
||||
}
|
||||
sender->Message_StringID(4, DOORS_SUCCESSFUL_PICK);
|
||||
}
|
||||
else
|
||||
{
|
||||
sender->Message_StringID(4, DOORS_INSUFFICIENT_SKILL);
|
||||
safe_delete(outapp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sender->Message_StringID(4, DOORS_NO_PICK);
|
||||
safe_delete(outapp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sender->Message_StringID(4, DOORS_CANT_PICK);
|
||||
safe_delete(outapp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // locked door and nothing to open it with
|
||||
// search for key on keyring
|
||||
if(sender->KeyRingCheck(keyneeded))
|
||||
{
|
||||
playerkey = keyneeded;
|
||||
sender->Message(4, "You got it open!"); // more debug spam
|
||||
if(!IsDoorOpen() || (opentype == 58))
|
||||
{
|
||||
md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
|
||||
}
|
||||
else
|
||||
{
|
||||
md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sender->Message_StringID(4, DOORS_LOCKED);
|
||||
safe_delete(outapp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
entity_list.QueueClients(sender, outapp, false);
|
||||
if(!IsDoorOpen() || (opentype == 58))
|
||||
{
|
||||
close_timer.Start();
|
||||
SetOpenState(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
close_timer.Disable();
|
||||
SetOpenState(false);
|
||||
}
|
||||
|
||||
//everything past this point assumes we opened the door
|
||||
//and met all the reqs for opening
|
||||
//everything to do with closed doors has already been taken care of
|
||||
//we return because we don't want people using teleports on an unlocked door (exploit!)
|
||||
if((md->action == CLOSE_DOOR && invert_state == 0) || (md->action == CLOSE_INVDOOR && invert_state == 1))
|
||||
{
|
||||
safe_delete(outapp);
|
||||
return;
|
||||
}
|
||||
|
||||
safe_delete(outapp);
|
||||
|
||||
if((GetTriggerDoorID() != 0) && (GetTriggerType() == 1))
|
||||
{
|
||||
Doors* triggerdoor = entity_list.FindDoor(GetTriggerDoorID());
|
||||
if(triggerdoor && !triggerdoor->triggered)
|
||||
{
|
||||
triggered=true;
|
||||
triggerdoor->HandleClick(sender, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
triggered=false;
|
||||
}
|
||||
}
|
||||
else if((GetTriggerDoorID() != 0) && (GetTriggerType() != 1))
|
||||
{
|
||||
Doors* triggerdoor = entity_list.FindDoor(GetTriggerDoorID());
|
||||
if(triggerdoor && !triggerdoor->triggered)
|
||||
{
|
||||
triggered=true;
|
||||
triggerdoor->HandleClick(sender, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
triggered=false;
|
||||
}
|
||||
}
|
||||
|
||||
if(((opentype == 57) || (opentype == 58)) && (strncmp(dest_zone, "NONE", strlen("NONE")) != 0))
|
||||
{ // Teleport door!
|
||||
if (( strncmp(dest_zone,zone_name,strlen(zone_name)) == 0) && (!keyneeded))
|
||||
{
|
||||
if(!keepoffkeyring)
|
||||
{
|
||||
sender->KeyRingAdd(playerkey);
|
||||
}
|
||||
sender->MovePC(zone->GetZoneID(), zone->GetInstanceID(), dest_x, dest_y, dest_z, dest_heading);
|
||||
}
|
||||
else if (( !IsDoorOpen() || opentype == 58 ) && (keyneeded && ((keyneeded == playerkey) || sender->GetGM())))
|
||||
{
|
||||
if(!keepoffkeyring)
|
||||
{
|
||||
sender->KeyRingAdd(playerkey);
|
||||
}
|
||||
if(database.GetZoneID(dest_zone) == zone->GetZoneID())
|
||||
{
|
||||
sender->MovePC(zone->GetZoneID(), zone->GetInstanceID(), dest_x, dest_y, dest_z, dest_heading);
|
||||
}
|
||||
else
|
||||
{
|
||||
sender->MovePC(database.GetZoneID(dest_zone), dest_instance_id, dest_x, dest_y, dest_z, dest_heading);
|
||||
}
|
||||
}
|
||||
if (( !IsDoorOpen() || opentype == 58 ) && (!keyneeded))
|
||||
{
|
||||
if(database.GetZoneID(dest_zone) == zone->GetZoneID())
|
||||
{
|
||||
sender->MovePC(zone->GetZoneID(), zone->GetInstanceID(), dest_x, dest_y, dest_z, dest_heading);
|
||||
}
|
||||
else
|
||||
{
|
||||
sender->MovePC(database.GetZoneID(dest_zone), dest_instance_id, dest_x, dest_y, dest_z, dest_heading);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Doors::NPCOpen(NPC* sender, bool alt_mode)
|
||||
{
|
||||
if(sender) {
|
||||
if(GetTriggerType() == 255 || GetTriggerDoorID() > 0 || GetLockpick() != 0 || GetKeyItem() != 0 || opentype == 59 || opentype == 58 || !sender->IsNPC()) { // this object isnt triggered or door is locked - NPCs should not open locked doors!
|
||||
return;
|
||||
}
|
||||
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct));
|
||||
MoveDoor_Struct* md=(MoveDoor_Struct*)outapp->pBuffer;
|
||||
md->doorid = door_id;
|
||||
md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
|
||||
entity_list.QueueCloseClients(sender,outapp,false,200);
|
||||
safe_delete(outapp);
|
||||
|
||||
if(!alt_mode) { // original function
|
||||
if(!isopen) {
|
||||
close_timer.Start();
|
||||
isopen=true;
|
||||
}
|
||||
else {
|
||||
close_timer.Disable();
|
||||
isopen=false;
|
||||
}
|
||||
}
|
||||
else { // alternative function
|
||||
close_timer.Start();
|
||||
isopen=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Doors::ForceOpen(Mob *sender, bool alt_mode)
|
||||
{
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct));
|
||||
MoveDoor_Struct* md=(MoveDoor_Struct*)outapp->pBuffer;
|
||||
md->doorid = door_id;
|
||||
md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
|
||||
entity_list.QueueClients(sender,outapp,false);
|
||||
safe_delete(outapp);
|
||||
|
||||
if(!alt_mode) { // original function
|
||||
if(!isopen) {
|
||||
close_timer.Start();
|
||||
isopen=true;
|
||||
}
|
||||
else {
|
||||
close_timer.Disable();
|
||||
isopen=false;
|
||||
}
|
||||
}
|
||||
else { // alternative function
|
||||
close_timer.Start();
|
||||
isopen=true;
|
||||
}
|
||||
}
|
||||
|
||||
void Doors::ForceClose(Mob *sender, bool alt_mode)
|
||||
{
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct));
|
||||
MoveDoor_Struct* md=(MoveDoor_Struct*)outapp->pBuffer;
|
||||
md->doorid = door_id;
|
||||
md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR; // change from original (open to close)
|
||||
entity_list.QueueClients(sender,outapp,false);
|
||||
safe_delete(outapp);
|
||||
|
||||
if(!alt_mode) { // original function
|
||||
if(!isopen) {
|
||||
close_timer.Start();
|
||||
isopen=true;
|
||||
}
|
||||
else {
|
||||
close_timer.Disable();
|
||||
isopen=false;
|
||||
}
|
||||
}
|
||||
else { // alternative function
|
||||
if(isopen)
|
||||
close_timer.Trigger();
|
||||
}
|
||||
}
|
||||
|
||||
void Doors::ToggleState(Mob *sender)
|
||||
{
|
||||
if(GetTriggerDoorID() > 0 || GetLockpick() != 0 || GetKeyItem() != 0 || opentype == 58 || opentype == 40) { // borrowed some NPCOpen criteria
|
||||
return;
|
||||
}
|
||||
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct));
|
||||
MoveDoor_Struct* md=(MoveDoor_Struct*)outapp->pBuffer;
|
||||
md->doorid = door_id;
|
||||
|
||||
if(!isopen) {
|
||||
md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
|
||||
isopen=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR;
|
||||
isopen=false;
|
||||
}
|
||||
|
||||
entity_list.QueueClients(sender,outapp,false);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
void Doors::DumpDoor(){
|
||||
LogFile->write(EQEMuLog::Debug,
|
||||
"db_id:%i door_id:%i zone_name:%s door_name:%s pos_x:%f pos_y:%f pos_z:%f heading:%f",
|
||||
db_id, door_id, zone_name, door_name, pos_x, pos_y, pos_z, heading);
|
||||
LogFile->write(EQEMuLog::Debug,
|
||||
"opentype:%i guild_id:%i lockpick:%i keyitem:%i nokeyring:%i trigger_door:%i trigger_type:%i door_param:%i open:%s",
|
||||
opentype, guild_id, lockpick, keyitem, nokeyring, trigger_door, trigger_type, door_param, (isopen) ? "open":"closed");
|
||||
LogFile->write(EQEMuLog::Debug,
|
||||
"dest_zone:%s dest_x:%f dest_y:%f dest_z:%f dest_heading:%f",
|
||||
dest_zone, dest_x, dest_y, dest_z, dest_heading);
|
||||
}
|
||||
|
||||
int32 ZoneDatabase::GetDoorsCount(uint32* oMaxID, const char *zone_name, int16 version) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
query = new char[256];
|
||||
sprintf(query, "SELECT MAX(id), count(*) FROM doors WHERE zone='%s' AND (version=%u OR version=-1)", zone_name, version);
|
||||
if (RunQuery(query, strlen(query), errbuf, &result)) {
|
||||
safe_delete_array(query);
|
||||
row = mysql_fetch_row(result);
|
||||
if (row != NULL && row[1] != 0) {
|
||||
int32 ret = atoi(row[1]);
|
||||
if (oMaxID) {
|
||||
if (row[0])
|
||||
*oMaxID = atoi(row[0]);
|
||||
else
|
||||
*oMaxID = 0;
|
||||
}
|
||||
mysql_free_result(result);
|
||||
return ret;
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else {
|
||||
cerr << "Error in GetDoorsCount query '" << query << "' " << errbuf << endl;
|
||||
safe_delete_array(query);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32 ZoneDatabase::GetDoorsCountPlusOne(const char *zone_name, int16 version) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
uint32 oMaxID = 0;
|
||||
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
query = new char[256];
|
||||
sprintf(query, "SELECT MAX(id) FROM doors WHERE zone='%s' AND version=%u", zone_name, version);
|
||||
if (RunQuery(query, strlen(query), errbuf, &result)) {
|
||||
safe_delete_array(query);
|
||||
row = mysql_fetch_row(result);
|
||||
if (row != NULL && row[1] != 0) {
|
||||
if (row[0])
|
||||
oMaxID = atoi(row[0]) + 1;
|
||||
else
|
||||
oMaxID = 0;
|
||||
mysql_free_result(result);
|
||||
return oMaxID;
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else {
|
||||
cerr << "Error in GetDoorsCountPlusOne query '" << query << "' " << errbuf << endl;
|
||||
safe_delete_array(query);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32 ZoneDatabase::GetDoorsDBCountPlusOne(const char *zone_name, int16 version) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
uint32 oMaxID = 0;
|
||||
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
query = new char[256];
|
||||
sprintf(query, "SELECT MAX(doorid) FROM doors WHERE zone='%s' AND (version=%u OR version=-1)", zone_name, version);
|
||||
if (RunQuery(query, strlen(query), errbuf, &result)) {
|
||||
safe_delete_array(query);
|
||||
row = mysql_fetch_row(result);
|
||||
if (row != NULL && row[1] != 0) {
|
||||
if (row[0])
|
||||
oMaxID = atoi(row[0]) + 1;
|
||||
else
|
||||
oMaxID = 0;
|
||||
mysql_free_result(result);
|
||||
return oMaxID;
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else {
|
||||
cerr << "Error in GetDoorsCountPlusOne query '" << query << "' " << errbuf << endl;
|
||||
safe_delete_array(query);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
extern "C" bool extDBLoadDoors(int32 iDoorCount, uint32 iMaxDoorID) { return database.DBLoadDoors(iDoorCount, iMaxDoorID); }
|
||||
const Door* ZoneDatabase::GetDoor(uint8 door_id, const char* zone_name) {
|
||||
for(uint32 i=0; i!=max_door_type;i++)
|
||||
{
|
||||
const Door* door;
|
||||
door = GetDoorDBID(i);
|
||||
if (!door)
|
||||
continue;
|
||||
if(door->door_id == door_id && strcasecmp(door->zone_name, zone_name) == 0)
|
||||
return door;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Door* ZoneDatabase::GetDoorDBID(uint32 db_id) {
|
||||
return EMuShareMemDLL.Doors.GetDoor(db_id);
|
||||
}
|
||||
|
||||
bool ZoneDatabase::LoadDoors() {
|
||||
if (!EMuShareMemDLL.Load())
|
||||
return false;
|
||||
int32 tmp = 0;
|
||||
tmp = GetDoorsCount(&max_door_type);
|
||||
if (tmp == -1) {
|
||||
cout << "Error: ZoneDatabase::LoadDoors-ShareMem: GetDoorsCount() returned < 0" << endl;
|
||||
return false;
|
||||
}
|
||||
bool ret = EMuShareMemDLL.Doors.DLLLoadDoors(&extDBLoadDoors, sizeof(Door), &tmp, &max_door_type);
|
||||
return ret;
|
||||
}*/
|
||||
|
||||
bool ZoneDatabase::LoadDoors(int32 iDoorCount, Door *into, const char *zone_name, int16 version) {
|
||||
LogFile->write(EQEMuLog::Status, "Loading Doors from database...");
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
// Door tmpDoor;
|
||||
MakeAnyLenString(&query, "SELECT id,doorid,zone,name,pos_x,pos_y,pos_z,heading,"
|
||||
"opentype,guild,lockpick,keyitem,nokeyring,triggerdoor,triggertype,dest_zone,dest_instance,dest_x,"
|
||||
"dest_y,dest_z,dest_heading,door_param,invert_state,incline,size,is_ldon_door,client_version_mask "
|
||||
"FROM doors WHERE zone='%s' AND (version=%u OR version=-1) ORDER BY doorid asc", zone_name, version);
|
||||
if (RunQuery(query, strlen(query), errbuf, &result)) {
|
||||
safe_delete_array(query);
|
||||
int32 r;
|
||||
for(r = 0; (row = mysql_fetch_row(result)); r++) {
|
||||
if(r >= iDoorCount) {
|
||||
cerr << "Error, Door Count of " << iDoorCount << " exceeded." << endl;
|
||||
break;
|
||||
}
|
||||
memset(&into[r], 0, sizeof(Door));
|
||||
into[r].db_id = atoi(row[0]);
|
||||
into[r].door_id = atoi(row[1]);
|
||||
strn0cpy(into[r].zone_name,row[2],32);
|
||||
strn0cpy(into[r].door_name,row[3],32);
|
||||
into[r].pos_x = (float)atof(row[4]);
|
||||
into[r].pos_y = (float)atof(row[5]);
|
||||
into[r].pos_z = (float)atof(row[6]);
|
||||
into[r].heading = (float)atof(row[7]);
|
||||
into[r].opentype = atoi(row[8]);
|
||||
into[r].guild_id = atoi(row[9]);
|
||||
into[r].lockpick = atoi(row[10]);
|
||||
into[r].keyitem = atoi(row[11]);
|
||||
into[r].nokeyring = atoi(row[12]);
|
||||
into[r].trigger_door = atoi(row[13]);
|
||||
into[r].trigger_type = atoi(row[14]);
|
||||
strn0cpy(into[r].dest_zone, row[15], 32);
|
||||
into[r].dest_instance_id = atoi(row[16]);
|
||||
into[r].dest_x = (float) atof(row[17]);
|
||||
into[r].dest_y = (float) atof(row[18]);
|
||||
into[r].dest_z = (float) atof(row[19]);
|
||||
into[r].dest_heading = (float) atof(row[20]);
|
||||
into[r].door_param=atoi(row[21]);
|
||||
into[r].invert_state=atoi(row[22]);
|
||||
into[r].incline=atoi(row[23]);
|
||||
into[r].size=atoi(row[24]);
|
||||
into[r].is_ldon_door=atoi(row[25]);
|
||||
into[r].client_version_mask = (uint32)strtoul(row[26], NULL, 10);
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "Error in DBLoadDoors query '" << query << "' " << errbuf << endl;
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Doors::SetLocation(float x, float y, float z)
|
||||
{
|
||||
entity_list.DespawnAllDoors();
|
||||
pos_x = x;
|
||||
pos_y = y;
|
||||
pos_z = z;
|
||||
entity_list.RespawnAllDoors();
|
||||
}
|
||||
|
||||
void Doors::SetX(float in) {
|
||||
entity_list.DespawnAllDoors();
|
||||
pos_x = in;
|
||||
entity_list.RespawnAllDoors();
|
||||
}
|
||||
void Doors::SetY(float in) {
|
||||
entity_list.DespawnAllDoors();
|
||||
pos_y = in;
|
||||
entity_list.RespawnAllDoors();
|
||||
}
|
||||
void Doors::SetZ(float in) {
|
||||
entity_list.DespawnAllDoors();
|
||||
pos_z = in;
|
||||
entity_list.RespawnAllDoors();
|
||||
}
|
||||
void Doors::SetHeading(float in) {
|
||||
entity_list.DespawnAllDoors();
|
||||
heading = in;
|
||||
entity_list.RespawnAllDoors();
|
||||
}
|
||||
|
||||
void Doors::SetIncline(int in) {
|
||||
entity_list.DespawnAllDoors();
|
||||
incline = in;
|
||||
entity_list.RespawnAllDoors();
|
||||
}
|
||||
|
||||
void Doors::SetOpenType(uint8 in) {
|
||||
entity_list.DespawnAllDoors();
|
||||
opentype = in;
|
||||
entity_list.RespawnAllDoors();
|
||||
}
|
||||
|
||||
void Doors::SetDoorName(char* name) {
|
||||
entity_list.DespawnAllDoors();
|
||||
memset(door_name, 0, sizeof(door_name));
|
||||
strncpy(door_name, name, sizeof(door_name));
|
||||
entity_list.RespawnAllDoors();
|
||||
}
|
||||
|
||||
void Doors::SetSize(uint16 in) {
|
||||
entity_list.DespawnAllDoors();
|
||||
size = in;
|
||||
entity_list.RespawnAllDoors();
|
||||
}
|
||||
|
||||
void Doors::CreateDatabaseEntry()
|
||||
{
|
||||
if(database.GetDoorsDBCountPlusOne(zone->GetShortName(), zone->GetInstanceVersion()) - 1 >= 255)
|
||||
{
|
||||
return;
|
||||
}
|
||||
database.InsertDoor(GetDoorDBID(), GetDoorID(), GetDoorName(), GetX(), GetY(), GetZ(), GetHeading(), GetOpenType(), GetGuildID(), GetLockpick(), GetKeyItem(), GetDoorParam(), GetInvertState(), GetIncline(), GetSize());
|
||||
}
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
#ifndef DOORS_H
|
||||
#define DOORS_H
|
||||
#include "../common/types.h"
|
||||
#include "../common/linked_list.h"
|
||||
#include "../common/timer.h"
|
||||
#include "../common/emu_opcodes.h"
|
||||
#include "../common/eq_packet_structs.h"
|
||||
#include "entity.h"
|
||||
#include "mob.h"
|
||||
#include "zonedump.h"
|
||||
|
||||
class Doors : public Entity
|
||||
{
|
||||
public:
|
||||
Doors(const Door* door);
|
||||
Doors(const char *dmodel, float dx, float dy, float dz, float dheading, uint8 dopentype = 58, uint16 dsize = 100);
|
||||
~Doors();
|
||||
bool IsDoor() const { return true; }
|
||||
void HandleClick(Client* sender, uint8 trigger);
|
||||
bool Process();
|
||||
uint8 GetDoorID() { return door_id; }
|
||||
uint32 GetDoorDBID() { return db_id; }
|
||||
uint32 GetGuildID() { return guild_id; }
|
||||
uint8 GetOpenType() { return opentype; }
|
||||
char* GetDoorName() { return door_name; }
|
||||
uint32 GetDoorParam() { return door_param; }
|
||||
int GetInvertState() { return invert_state; }
|
||||
float GetX() { return pos_x; }
|
||||
float GetY() { return pos_y; }
|
||||
float GetZ() { return pos_z; }
|
||||
float GetHeading() { return heading; }
|
||||
int GetIncline() { return incline; }
|
||||
bool triggered;
|
||||
void SetOpenState(bool st) { isopen = st; }
|
||||
bool IsDoorOpen() { return isopen; }
|
||||
|
||||
uint8 GetTriggerDoorID() { return trigger_door; }
|
||||
uint8 GetTriggerType() { return trigger_type; }
|
||||
|
||||
uint32 GetKeyItem() { return keyitem; }
|
||||
void SetKeyItem(uint32 in) { keyitem = in; }
|
||||
uint8 GetNoKeyring() { return nokeyring; }
|
||||
void SetNoKeyring(uint8 in) { nokeyring = in; }
|
||||
uint16 GetLockpick() { return lockpick; }
|
||||
void SetLockpick(uint16 in) { lockpick = in; }
|
||||
uint16 GetSize() { return size; }
|
||||
void SetGuildID(uint32 guild_id) { this->guild_id = guild_id; }
|
||||
|
||||
uint32 GetEntityID() { return entity_id; }
|
||||
void SetEntityID(uint32 entity) { entity_id = entity; }
|
||||
|
||||
void DumpDoor();
|
||||
float GetDestX() { return dest_x; }
|
||||
float GetDestY() { return dest_y; }
|
||||
float GetDestZ() { return dest_z; }
|
||||
float GetDestHeading() { return dest_heading; }
|
||||
|
||||
uint8 IsLDoNDoor() { return is_ldon_door; }
|
||||
uint32 GetClientVersionMask() { return client_version_mask; }
|
||||
|
||||
void NPCOpen(NPC* sender, bool alt_mode=false);
|
||||
void ForceOpen(Mob *sender, bool alt_mode=false);
|
||||
void ForceClose(Mob *sender, bool alt_mode=false);
|
||||
void ToggleState(Mob *sender);
|
||||
|
||||
void SetX(float in);
|
||||
void SetY(float in);
|
||||
void SetZ(float in);
|
||||
void SetHeading(float in);
|
||||
void SetIncline(int in);
|
||||
void SetDoorName(char* name);
|
||||
void SetOpenType(uint8 in);
|
||||
void SetLocation(float x, float y, float z);
|
||||
void SetSize(uint16 size);
|
||||
void CreateDatabaseEntry();
|
||||
|
||||
private:
|
||||
|
||||
uint32 db_id;
|
||||
uint8 door_id;
|
||||
char zone_name[32];
|
||||
char door_name[32];
|
||||
float pos_x;
|
||||
float pos_y;
|
||||
float pos_z;
|
||||
float heading;
|
||||
int incline;
|
||||
uint8 opentype;
|
||||
uint32 guild_id;
|
||||
uint16 lockpick;
|
||||
uint32 keyitem;
|
||||
uint8 nokeyring;
|
||||
uint8 trigger_door;
|
||||
uint8 trigger_type;
|
||||
uint32 door_param;
|
||||
uint16 size;
|
||||
int invert_state;
|
||||
uint32 entity_id;
|
||||
bool isopen;
|
||||
Timer close_timer;
|
||||
//Timer trigger_timer;
|
||||
|
||||
char dest_zone[16];
|
||||
int dest_instance_id;
|
||||
float dest_x;
|
||||
float dest_y;
|
||||
float dest_z;
|
||||
float dest_heading;
|
||||
|
||||
uint8 is_ldon_door;
|
||||
uint32 client_version_mask;
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,841 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "../common/debug.h"
|
||||
#include "masterentity.h"
|
||||
#include "worldserver.h"
|
||||
#include "zonedb.h"
|
||||
#include "spdat.h"
|
||||
#include "../common/packet_dump.h"
|
||||
#include "../common/packet_functions.h"
|
||||
#include "petitions.h"
|
||||
#include "../common/serverinfo.h"
|
||||
#include "../common/ZoneNumbers.h"
|
||||
#include "../common/moremath.h"
|
||||
#include "../common/guilds.h"
|
||||
#include "StringIDs.h"
|
||||
#include "NpcAI.h"
|
||||
|
||||
float Client::GetActSpellRange(uint16 spell_id, float range, bool IsBard)
|
||||
{
|
||||
float extrange = 100;
|
||||
|
||||
extrange += GetFocusEffect(focusRange, spell_id);
|
||||
|
||||
return (range * extrange) / 100;
|
||||
}
|
||||
|
||||
|
||||
int32 Client::Additional_SpellDmg(uint16 spell_id, bool bufftick)
|
||||
{
|
||||
int32 spell_dmg = 0;
|
||||
spell_dmg += GetFocusEffect(focusFF_Damage_Amount, spell_id);
|
||||
spell_dmg += GetFocusEffect(focusSpellDamage, spell_id);
|
||||
|
||||
//For DOTs you need to apply the damage over the duration of the dot to each tick (this is how live did it)
|
||||
if (bufftick){
|
||||
int duration = CalcBuffDuration(this, this, spell_id);
|
||||
if (duration > 0)
|
||||
return spell_dmg /= duration;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
return spell_dmg;
|
||||
}
|
||||
|
||||
//Scale all NPC spell Damage via $npc->SetSpellFocusDMG(value)
|
||||
//Direct Damage is checked in Mob::SpellEffect [spell_effects.cpp]
|
||||
//DoT Damage is checked in Mob::DoBuffTic [spell_effects.cpp] (This was added for npcs in that routine)
|
||||
int32 NPC::GetActSpellDamage(uint16 spell_id, int32 value) {
|
||||
|
||||
int32 modifier = 100;
|
||||
|
||||
modifier += SpellFocusDMG;
|
||||
|
||||
return (value * modifier / 100);
|
||||
}
|
||||
|
||||
int32 Client::GetActSpellDamage(uint16 spell_id, int32 value) {
|
||||
// Important variables:
|
||||
// value: the actual damage after resists, passed from Mob::SpellEffect
|
||||
// modifier: modifier to damage (from spells & focus effects?)
|
||||
// ratio: % of the modifier to apply (from AAs & natural bonus?)
|
||||
// chance: critital chance %
|
||||
|
||||
int32 modifier = 100;
|
||||
int16 spell_dmg = 0;
|
||||
|
||||
|
||||
//Dunno if this makes sense:
|
||||
if (spells[spell_id].resisttype > 0)
|
||||
modifier += GetFocusEffect((focusType)(0-spells[spell_id].resisttype), spell_id);
|
||||
|
||||
|
||||
int tt = spells[spell_id].targettype;
|
||||
if (tt == ST_UndeadAE || tt == ST_Undead || tt == ST_Summoned) {
|
||||
//undead/summoned spells
|
||||
modifier += GetFocusEffect(focusImprovedUndeadDamage, spell_id);
|
||||
} else {
|
||||
//damage spells.
|
||||
modifier += GetFocusEffect(focusImprovedDamage, spell_id);
|
||||
modifier += GetFocusEffect(focusSpellEffectiveness, spell_id);
|
||||
modifier += GetFocusEffect(focusImprovedDamage2, spell_id);
|
||||
}
|
||||
|
||||
// Need to scale HT damage differently after level 40! It no longer scales by the constant value in the spell file. It scales differently, instead of 10 more damage per level, it does 30 more damage per level. So we multiply the level minus 40 times 20 if they are over level 40.
|
||||
if ( spell_id == SPELL_HARM_TOUCH || spell_id == SPELL_HARM_TOUCH2 || spell_id == SPELL_IMP_HARM_TOUCH ) {
|
||||
if (this->GetLevel() > 40)
|
||||
value -= (this->GetLevel() - 40) * 20;
|
||||
}
|
||||
|
||||
//This adds the extra damage from the AA Unholy Touch, 450 per level to the AA Improved Harm TOuch.
|
||||
if (spell_id == SPELL_IMP_HARM_TOUCH) { //Improved Harm Touch
|
||||
value -= GetAA(aaUnholyTouch) * 450; //Unholy Touch
|
||||
}
|
||||
|
||||
// This adds the extra damage for the AA's Consumption of the Soul and Improved Consumption of the Soul, 200 per level to the AA Leech Curse for Shadowknights.
|
||||
if (spell_id == SPELL_LEECH_TOUCH) { //Leech Touch
|
||||
value -= GetAA(aaConsumptionoftheSoul) * 200; //Consumption of the Soul
|
||||
value -= GetAA(aaImprovedConsumptionofSoul) * 200; //Improved Consumption of the Soul
|
||||
}
|
||||
|
||||
//spell crits, dont make sense if cast on self.
|
||||
if(tt != ST_Self) {
|
||||
// item SpellDmg bonus
|
||||
// Formula = SpellDmg * (casttime + recastime) / 7; Cant trigger off spell less than 5 levels below and cant cause more dmg than the spell itself.
|
||||
if(this->itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) {
|
||||
spell_dmg = this->itembonuses.SpellDmg * (spells[spell_id].cast_time + spells[spell_id].recast_time) / 7000;
|
||||
if(spell_dmg > -value)
|
||||
spell_dmg = -value;
|
||||
}
|
||||
|
||||
// Spell-based SpellDmg adds directly but it restricted by focuses.
|
||||
spell_dmg += Additional_SpellDmg(spell_id);
|
||||
|
||||
int chance = RuleI(Spells, BaseCritChance);
|
||||
int32 ratio = RuleI(Spells, BaseCritRatio);
|
||||
|
||||
chance += itembonuses.CriticalSpellChance + spellbonuses.CriticalSpellChance + aabonuses.CriticalSpellChance;
|
||||
ratio += itembonuses.SpellCritDmgIncrease + spellbonuses.SpellCritDmgIncrease + aabonuses.SpellCritDmgIncrease;
|
||||
|
||||
if(GetClass() == WIZARD) {
|
||||
if (GetLevel() >= RuleI(Spells, WizCritLevel)) {
|
||||
chance += RuleI(Spells, WizCritChance);
|
||||
ratio += RuleI(Spells, WizCritRatio);
|
||||
}
|
||||
if(aabonuses.SpellCritDmgIncrease > 0) // wizards get an additional bonus
|
||||
ratio += aabonuses.SpellCritDmgIncrease * 1.5; //108%, 115%, 124%, close to Graffe's 207%, 215%, & 225%
|
||||
}
|
||||
|
||||
//Improved Harm Touch is a guaranteed crit if you have at least one level of SCF.
|
||||
if (spell_id == SPELL_IMP_HARM_TOUCH) {
|
||||
if ( (GetAA(aaSpellCastingFury) > 0) && (GetAA(aaUnholyTouch) > 0) )
|
||||
chance = 100;
|
||||
}
|
||||
|
||||
/*
|
||||
//Handled in aa_effects will focus spells from 'spellgroup=99'. (SK life tap from buff procs)
|
||||
//If you are using an older spell file table (Pre SOF)...
|
||||
//Use SQL optional_EnableSoulAbrasionAA to update your spells table to properly use the effect.
|
||||
//If you do not want to update your table then you may want to enable this.
|
||||
if(tt == ST_Tap) {
|
||||
if(spells[spell_id].classes[SHADOWKNIGHT-1] >= 254 && spell_id != SPELL_LEECH_TOUCH){
|
||||
if(ratio < 100) //chance increase and ratio are made up, not confirmed
|
||||
ratio = 100;
|
||||
|
||||
switch (GetAA(aaSoulAbrasion))
|
||||
{
|
||||
case 1:
|
||||
modifier += 100;
|
||||
break;
|
||||
case 2:
|
||||
modifier += 200;
|
||||
break;
|
||||
case 3:
|
||||
modifier += 300;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (chance > 0) {
|
||||
mlog(SPELLS__CRITS, "Attempting spell crit. Spell: %s (%d), Value: %d, Modifier: %d, Chance: %d, Ratio: %d", spells[spell_id].name, spell_id, value, modifier, chance, ratio);
|
||||
if(MakeRandomInt(0,100) <= chance) {
|
||||
modifier += modifier*ratio/100;
|
||||
spell_dmg *= 2;
|
||||
mlog(SPELLS__CRITS, "Spell crit successful. Final damage modifier: %d, Final Damage: %d", modifier, (value * modifier / 100) - spell_dmg);
|
||||
entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s delivers a critical blast! (%d)", GetName(), (-value * modifier / 100) + spell_dmg);
|
||||
} else
|
||||
mlog(SPELLS__CRITS, "Spell crit failed. Final Damage Modifier: %d, Final Damage: %d", modifier, (value * modifier / 100) - spell_dmg);
|
||||
}
|
||||
}
|
||||
|
||||
return ((value * modifier / 100) - spell_dmg);
|
||||
}
|
||||
|
||||
int32 Client::GetActDoTDamage(uint16 spell_id, int32 value) {
|
||||
|
||||
int32 modifier = 100;
|
||||
int16 spell_dmg = 0;
|
||||
int16 critChance = 0;
|
||||
int32 ratio = 0;
|
||||
|
||||
modifier += GetFocusEffect(focusImprovedDamage, spell_id);
|
||||
critChance += itembonuses.CriticalDoTChance + spellbonuses.CriticalDoTChance + aabonuses.CriticalDoTChance;
|
||||
ratio += itembonuses.DotCritDmgIncrease + spellbonuses.DotCritDmgIncrease + aabonuses.DotCritDmgIncrease;
|
||||
spell_dmg += Additional_SpellDmg(spell_id,true);
|
||||
|
||||
// since DOTs are the Necromancer forte, give an innate bonus (Kayen: Is this a real bonus?)
|
||||
// however, no chance to crit unless they've trained atleast one level in the AA first
|
||||
if (GetClass() == NECROMANCER && critChance > 0)
|
||||
critChance += 5;
|
||||
|
||||
if (critChance > 0){
|
||||
if (MakeRandomInt(0, 99) < critChance){
|
||||
modifier += modifier*ratio/100;
|
||||
return (((value*modifier/100)-spell_dmg)*2);
|
||||
}
|
||||
}
|
||||
|
||||
return ((value*modifier/100)-spell_dmg);
|
||||
|
||||
}
|
||||
|
||||
//Scale all NPC spell healing via SetSpellFocusHeal(value)
|
||||
int32 NPC::GetActSpellHealing(uint16 spell_id, int32 value) {
|
||||
|
||||
int32 modifier = 100;
|
||||
modifier += SpellFocusHeal;
|
||||
|
||||
// Check for buffs that affect the healrate of the target
|
||||
if(this->GetTarget())
|
||||
{
|
||||
value += value * GetHealRate(spell_id) / 100;
|
||||
}
|
||||
|
||||
return (value * modifier / 100);
|
||||
}
|
||||
|
||||
int32 Client::Additional_Heal(uint16 spell_id)
|
||||
{
|
||||
int32 heal_amt = 0;
|
||||
|
||||
heal_amt += GetFocusEffect(focusAdditionalHeal, spell_id);
|
||||
heal_amt += GetFocusEffect(focusAdditionalHeal2, spell_id);
|
||||
|
||||
if (heal_amt){
|
||||
int duration = CalcBuffDuration(this, this, spell_id);
|
||||
if (duration > 0)
|
||||
return heal_amt /= duration;
|
||||
}
|
||||
|
||||
return heal_amt;
|
||||
}
|
||||
|
||||
int32 Client::GetActSpellHealing(uint16 spell_id, int32 value) {
|
||||
|
||||
int32 modifier = 100;
|
||||
int16 heal_amt = 0;
|
||||
modifier += GetFocusEffect(focusImprovedHeal, spell_id);
|
||||
modifier += GetFocusEffect(focusSpellEffectiveness, spell_id);
|
||||
heal_amt += Additional_Heal(spell_id);
|
||||
int chance = 0;
|
||||
|
||||
// Instant Heals
|
||||
if(spells[spell_id].buffduration < 1)
|
||||
{
|
||||
// Formula = HealAmt * (casttime + recastime) / 7; Cant trigger off spell less than 5 levels below and cant heal more than the spell itself.
|
||||
if(this->itembonuses.HealAmt && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) {
|
||||
heal_amt = this->itembonuses.HealAmt * (spells[spell_id].cast_time + spells[spell_id].recast_time) / 7000;
|
||||
if(heal_amt > value)
|
||||
heal_amt = value;
|
||||
}
|
||||
|
||||
// Check for buffs that affect the healrate of the target and critical heal rate of target
|
||||
if(GetTarget()){
|
||||
value += value * GetHealRate(spell_id) / 100;
|
||||
chance += GetCriticalHealRate(spell_id);
|
||||
}
|
||||
|
||||
//Live AA - Healing Gift, Theft of Life
|
||||
chance += itembonuses.CriticalHealChance + spellbonuses.CriticalHealChance + aabonuses.CriticalHealChance;
|
||||
|
||||
if(MakeRandomInt(0,99) < chance) {
|
||||
entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s performs an exceptional heal! (%d)", GetName(), ((value * modifier / 50) + heal_amt*2));
|
||||
return ((value * modifier / 50) + heal_amt*2);
|
||||
}
|
||||
else{
|
||||
return ((value * modifier / 100) + heal_amt);
|
||||
}
|
||||
}
|
||||
// Hots
|
||||
else {
|
||||
chance += itembonuses.CriticalHealChance + spellbonuses.CriticalHealChance + aabonuses.CriticalHealChance;
|
||||
if(MakeRandomInt(0,99) < chance)
|
||||
return ((value * modifier / 50) + heal_amt*2);
|
||||
}
|
||||
return ((value * modifier / 100) + heal_amt);
|
||||
}
|
||||
|
||||
int32 Client::GetActSpellCost(uint16 spell_id, int32 cost)
|
||||
{
|
||||
// Formula = Unknown exact, based off a random percent chance up to mana cost(after focuses) of the cast spell
|
||||
if(this->itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
|
||||
{
|
||||
int16 mana_back = this->itembonuses.Clairvoyance * MakeRandomInt(1, 100) / 100;
|
||||
// Doesnt generate mana, so best case is a free spell
|
||||
if(mana_back > cost)
|
||||
mana_back = cost;
|
||||
|
||||
cost -= mana_back;
|
||||
}
|
||||
|
||||
// This formula was derived from the following resource:
|
||||
// http://www.eqsummoners.com/eq1/specialization-library.html
|
||||
// WildcardX
|
||||
float PercentManaReduction = 0;
|
||||
float SpecializeSkill = GetSpecializeSkillValue(spell_id);
|
||||
int SuccessChance = MakeRandomInt(0, 100);
|
||||
|
||||
float bonus = 1.0;
|
||||
switch(GetAA(aaSpellCastingMastery))
|
||||
{
|
||||
case 1:
|
||||
bonus += 0.05;
|
||||
break;
|
||||
case 2:
|
||||
bonus += 0.15;
|
||||
break;
|
||||
case 3:
|
||||
bonus += 0.30;
|
||||
break;
|
||||
}
|
||||
|
||||
bonus += 0.05 * GetAA(aaAdvancedSpellCastingMastery);
|
||||
|
||||
if(SuccessChance <= (SpecializeSkill * 0.3 * bonus))
|
||||
{
|
||||
PercentManaReduction = 1 + 0.05 * SpecializeSkill;
|
||||
switch(GetAA(aaSpellCastingMastery))
|
||||
{
|
||||
case 1:
|
||||
PercentManaReduction += 2.5;
|
||||
break;
|
||||
case 2:
|
||||
PercentManaReduction += 5.0;
|
||||
break;
|
||||
case 3:
|
||||
PercentManaReduction += 10.0;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(GetAA(aaAdvancedSpellCastingMastery))
|
||||
{
|
||||
case 1:
|
||||
PercentManaReduction += 2.5;
|
||||
break;
|
||||
case 2:
|
||||
PercentManaReduction += 5.0;
|
||||
break;
|
||||
case 3:
|
||||
PercentManaReduction += 10.0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int16 focus_redux = GetFocusEffect(focusManaCost, spell_id);
|
||||
|
||||
if(focus_redux > 0)
|
||||
{
|
||||
PercentManaReduction += MakeRandomFloat(1, (double)focus_redux);
|
||||
}
|
||||
|
||||
cost -= (cost * (PercentManaReduction / 100));
|
||||
|
||||
// Gift of Mana - reduces spell cost to 1 mana
|
||||
if(focus_redux >= 100) {
|
||||
uint32 buff_max = GetMaxTotalSlots();
|
||||
for (int buffSlot = 0; buffSlot < buff_max; buffSlot++) {
|
||||
if (buffs[buffSlot].spellid == 0 || buffs[buffSlot].spellid >= SPDAT_RECORDS)
|
||||
continue;
|
||||
|
||||
if(IsEffectInSpell(buffs[buffSlot].spellid, SE_ReduceManaCost)) {
|
||||
if(CalcFocusEffect(focusManaCost, buffs[buffSlot].spellid, spell_id) == 100)
|
||||
cost = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(cost < 0)
|
||||
cost = 0;
|
||||
|
||||
return cost;
|
||||
}
|
||||
|
||||
int32 Client::GetActSpellDuration(uint16 spell_id, int32 duration)
|
||||
{
|
||||
int increase = 100;
|
||||
increase += GetFocusEffect(focusSpellDuration, spell_id);
|
||||
int tic_inc = 0;
|
||||
tic_inc = GetFocusEffect(focusSpellDurByTic, spell_id);
|
||||
|
||||
if(IsBeneficialSpell(spell_id))
|
||||
{
|
||||
switch(GetAA(aaSpellCastingReinforcement)) {
|
||||
case 1:
|
||||
increase += 5;
|
||||
break;
|
||||
case 2:
|
||||
increase += 15;
|
||||
break;
|
||||
case 3:
|
||||
increase += 30;
|
||||
if (GetAA(aaSpellCastingReinforcementMastery) == 1)
|
||||
increase += 20;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(IsMezSpell(spell_id)) {
|
||||
tic_inc += GetAA(aaMesmerizationMastery);
|
||||
}
|
||||
|
||||
return (((duration * increase) / 100) + tic_inc);
|
||||
}
|
||||
|
||||
int32 Client::GetActSpellCasttime(uint16 spell_id, int32 casttime)
|
||||
{
|
||||
int32 cast_reducer = 0;
|
||||
cast_reducer += GetFocusEffect(focusSpellHaste, spell_id);
|
||||
|
||||
//this function loops through the effects of spell_id many times
|
||||
//could easily be consolidated.
|
||||
|
||||
if (GetLevel() >= 51 && casttime >= 3000 && !BeneficialSpell(spell_id)
|
||||
&& (GetClass() == SHADOWKNIGHT || GetClass() == RANGER
|
||||
|| GetClass() == PALADIN || GetClass() == BEASTLORD ))
|
||||
cast_reducer += (GetLevel()-50)*3;
|
||||
|
||||
//LIVE AA SpellCastingDeftness, QuickBuff, QuickSummoning, QuickEvacuation, QuickDamage
|
||||
|
||||
if (cast_reducer > RuleI(Spells, MaxCastTimeReduction))
|
||||
cast_reducer = RuleI(Spells, MaxCastTimeReduction);
|
||||
|
||||
casttime = (casttime*(100 - cast_reducer)/100);
|
||||
|
||||
return casttime;
|
||||
}
|
||||
|
||||
bool Client::TrainDiscipline(uint32 itemid) {
|
||||
|
||||
//get the item info
|
||||
const Item_Struct *item = database.GetItem(itemid);
|
||||
if(item == NULL) {
|
||||
Message(13, "Unable to find the tome you turned in!");
|
||||
LogFile->write(EQEMuLog::Error, "Unable to find turned in tome id %lu\n", (unsigned long)itemid);
|
||||
return(false);
|
||||
}
|
||||
|
||||
if(item->ItemClass != ItemClassCommon || item->ItemType != ItemTypeSpell) {
|
||||
Message(13, "Invalid item type, you cannot learn from this item.");
|
||||
//summon them the item back...
|
||||
SummonItem(itemid);
|
||||
return(false);
|
||||
}
|
||||
|
||||
//Need a way to determine the difference between a spell and a tome
|
||||
//so they cant turn in a spell and get it as a discipline
|
||||
//this is kinda a hack:
|
||||
if(!(
|
||||
item->Name[0] == 'T' &&
|
||||
item->Name[1] == 'o' &&
|
||||
item->Name[2] == 'm' &&
|
||||
item->Name[3] == 'e' &&
|
||||
item->Name[4] == ' '
|
||||
)) {
|
||||
Message(13, "This item is not a tome.");
|
||||
//summon them the item back...
|
||||
SummonItem(itemid);
|
||||
return(false);
|
||||
}
|
||||
|
||||
int myclass = GetClass();
|
||||
if(myclass == WIZARD || myclass == ENCHANTER || myclass == MAGICIAN || myclass == NECROMANCER) {
|
||||
Message(13, "Your class cannot learn from this tome.");
|
||||
//summon them the item back...
|
||||
SummonItem(itemid);
|
||||
return(false);
|
||||
}
|
||||
|
||||
//make sure we can train this...
|
||||
//can we use the item?
|
||||
uint32 cbit = 1 << (myclass-1);
|
||||
if(!(item->Classes & cbit)) {
|
||||
Message(13, "Your class cannot learn from this tome.");
|
||||
//summon them the item back...
|
||||
SummonItem(itemid);
|
||||
return(false);
|
||||
}
|
||||
|
||||
uint32 spell_id = item->Scroll.Effect;
|
||||
if(!IsValidSpell(spell_id)) {
|
||||
Message(13, "This tome contains invalid knowledge.");
|
||||
return(false);
|
||||
}
|
||||
|
||||
//can we use the spell?
|
||||
const SPDat_Spell_Struct &spell = spells[spell_id];
|
||||
uint8 level_to_use = spell.classes[myclass - 1];
|
||||
if(level_to_use == 255) {
|
||||
Message(13, "Your class cannot learn from this tome.");
|
||||
//summon them the item back...
|
||||
SummonItem(itemid);
|
||||
return(false);
|
||||
}
|
||||
|
||||
if(level_to_use > GetLevel()) {
|
||||
Message(13, "You must be at least level %d to learn this discipline.", level_to_use);
|
||||
//summon them the item back...
|
||||
SummonItem(itemid);
|
||||
return(false);
|
||||
}
|
||||
|
||||
//add it to PP.
|
||||
int r;
|
||||
for(r = 0; r < MAX_PP_DISCIPLINES; r++) {
|
||||
if(m_pp.disciplines.values[r] == spell_id) {
|
||||
Message(13, "You already know this discipline.");
|
||||
//summon them the item back...
|
||||
SummonItem(itemid);
|
||||
return(false);
|
||||
} else if(m_pp.disciplines.values[r] == 0) {
|
||||
m_pp.disciplines.values[r] = spell_id;
|
||||
SendDisciplineUpdate();
|
||||
Message(0, "You have learned a new discipline!");
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
Message(13, "You have learned too many disciplines and can learn no more.");
|
||||
return(false);
|
||||
}
|
||||
|
||||
void Client::SendDisciplineUpdate() {
|
||||
//this dosent seem to work right now
|
||||
|
||||
EQApplicationPacket app(OP_DisciplineUpdate, sizeof(Disciplines_Struct));
|
||||
Disciplines_Struct *d = (Disciplines_Struct*)app.pBuffer;
|
||||
//dunno why I dont just send the one from m_pp
|
||||
memcpy(d, &m_pp.disciplines, sizeof(m_pp.disciplines));
|
||||
|
||||
QueuePacket(&app);
|
||||
}
|
||||
|
||||
bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
|
||||
// Dont let client waste a reuse timer if they can't use the disc
|
||||
if (IsStunned() || IsFeared() || IsMezzed() || IsAmnesiad() || IsPet())
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
//make sure we have the spell...
|
||||
int r;
|
||||
for(r = 0; r < MAX_PP_DISCIPLINES; r++) {
|
||||
if(m_pp.disciplines.values[r] == spell_id)
|
||||
break;
|
||||
}
|
||||
if(r == MAX_PP_DISCIPLINES)
|
||||
return(false); //not found.
|
||||
|
||||
//Check the disc timer
|
||||
pTimerType DiscTimer = pTimerDisciplineReuseStart + spells[spell_id].EndurTimerIndex;
|
||||
if(!p_timers.Expired(&database, DiscTimer)) {
|
||||
/*char val1[20]={0};*/ //unused
|
||||
/*char val2[20]={0};*/ //unused
|
||||
uint32 remain = p_timers.GetRemainingTime(DiscTimer);
|
||||
//Message_StringID(0, DISCIPLINE_CANUSEIN, ConvertArray((remain)/60,val1), ConvertArray(remain%60,val2));
|
||||
Message(0, "You can use this discipline in %d minutes %d seconds.", ((remain)/60), (remain%60));
|
||||
return(false);
|
||||
}
|
||||
|
||||
//make sure we can use it..
|
||||
if(!IsValidSpell(spell_id)) {
|
||||
Message(13, "This tome contains invalid knowledge.");
|
||||
return(false);
|
||||
}
|
||||
|
||||
//can we use the spell?
|
||||
const SPDat_Spell_Struct &spell = spells[spell_id];
|
||||
uint8 level_to_use = spell.classes[GetClass() - 1];
|
||||
if(level_to_use == 255) {
|
||||
Message(13, "Your class cannot learn from this tome.");
|
||||
//should summon them a new one...
|
||||
return(false);
|
||||
}
|
||||
|
||||
if(level_to_use > GetLevel()) {
|
||||
Message_StringID(13, DISC_LEVEL_USE_ERROR);
|
||||
//should summon them a new one...
|
||||
return(false);
|
||||
}
|
||||
|
||||
if(GetEndurance() > spell.EndurCost) {
|
||||
SetEndurance(GetEndurance() - spell.EndurCost);
|
||||
} else {
|
||||
Message(11, "You are too fatigued to use this skill right now.");
|
||||
return(false);
|
||||
}
|
||||
|
||||
if(spell.recast_time > 0)
|
||||
{
|
||||
uint32 reduced_recast = spell.recast_time / 1000;
|
||||
reduced_recast -= CastToClient()->GetFocusEffect(focusReduceRecastTime, spell_id);
|
||||
if(reduced_recast < 0)
|
||||
reduced_recast = 0;
|
||||
|
||||
CastSpell(spell_id, target, DISCIPLINE_SPELL_SLOT, -1, -1, 0, -1, (uint32)DiscTimer, reduced_recast);
|
||||
if(spells[spell_id].EndurTimerIndex < MAX_DISCIPLINE_TIMERS)
|
||||
{
|
||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_DisciplineTimer, sizeof(DisciplineTimer_Struct));
|
||||
DisciplineTimer_Struct *dts = (DisciplineTimer_Struct *)outapp->pBuffer;
|
||||
dts->TimerID = spells[spell_id].EndurTimerIndex;
|
||||
dts->Duration = reduced_recast;
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CastSpell(spell_id, target, DISCIPLINE_SPELL_SLOT);
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
|
||||
void EntityList::AETaunt(Client* taunter, float range) {
|
||||
LinkedListIterator<NPC*> iterator(npc_list);
|
||||
|
||||
if(range == 0) {
|
||||
range = 100; //arbitrary default...
|
||||
}
|
||||
|
||||
range = range * range;
|
||||
|
||||
iterator.Reset();
|
||||
while(iterator.MoreElements())
|
||||
{
|
||||
NPC * them = iterator.GetData();
|
||||
float zdiff = taunter->GetZ() - them->GetZ();
|
||||
if (zdiff < 0)
|
||||
zdiff *= -1;
|
||||
if (zdiff < 10
|
||||
&& taunter->IsAttackAllowed(them)
|
||||
&& taunter->DistNoRootNoZ(*them) <= range) {
|
||||
|
||||
if (taunter->CheckLosFN(them)) {
|
||||
taunter->Taunt(them, true);
|
||||
}
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
}
|
||||
|
||||
// solar: causes caster to hit every mob within dist range of center with
|
||||
// spell_id.
|
||||
// NPC spells will only affect other NPCs with compatible faction
|
||||
void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster, int16 resist_adjust)
|
||||
{
|
||||
LinkedListIterator<Mob*> iterator(mob_list);
|
||||
Mob *curmob;
|
||||
|
||||
float dist = caster->GetAOERange(spell_id);
|
||||
float dist2 = dist * dist;
|
||||
|
||||
bool bad = IsDetrimentalSpell(spell_id);
|
||||
bool isnpc = caster->IsNPC();
|
||||
const int MAX_TARGETS_ALLOWED = 4;
|
||||
int iCounter = 0;
|
||||
|
||||
for(iterator.Reset(); iterator.MoreElements(); iterator.Advance())
|
||||
{
|
||||
curmob = iterator.GetData();
|
||||
if(curmob == center) //do not affect center
|
||||
continue;
|
||||
if(curmob == caster && !affect_caster) //watch for caster too
|
||||
continue;
|
||||
if(center->DistNoRoot(*curmob) > dist2) //make sure they are in range
|
||||
continue;
|
||||
if(isnpc && curmob->IsNPC()) { //check npc->npc casting
|
||||
FACTION_VALUE f = curmob->GetReverseFactionCon(caster);
|
||||
if(bad) {
|
||||
//affect mobs that are on our hate list, or
|
||||
//which have bad faction with us
|
||||
if( ! (caster->CheckAggro(curmob) || f == FACTION_THREATENLY || f == FACTION_SCOWLS) )
|
||||
continue;
|
||||
} else {
|
||||
//only affect mobs we would assist.
|
||||
if( ! (f <= FACTION_AMIABLE))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
//finally, make sure they are within range
|
||||
if(bad) {
|
||||
if(!caster->IsAttackAllowed(curmob, true))
|
||||
continue;
|
||||
if(!center->CheckLosFN(curmob))
|
||||
continue;
|
||||
}
|
||||
|
||||
//if we get here... cast the spell.
|
||||
if(IsTargetableAESpell(spell_id) && bad)
|
||||
{
|
||||
if(iCounter < MAX_TARGETS_ALLOWED)
|
||||
{
|
||||
caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust);
|
||||
}
|
||||
|
||||
if(!isnpc) //npcs are not target limited...
|
||||
iCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityList::MassGroupBuff(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster)
|
||||
{
|
||||
LinkedListIterator<Mob*> iterator(mob_list);
|
||||
Mob *curmob;
|
||||
|
||||
float dist = caster->GetAOERange(spell_id);
|
||||
float dist2 = dist * dist;
|
||||
|
||||
bool bad = IsDetrimentalSpell(spell_id);
|
||||
|
||||
for(iterator.Reset(); iterator.MoreElements(); iterator.Advance())
|
||||
{
|
||||
curmob = iterator.GetData();
|
||||
if(curmob == center) //do not affect center
|
||||
continue;
|
||||
if(curmob == caster && !affect_caster) //watch for caster too
|
||||
continue;
|
||||
if(center->DistNoRoot(*curmob) > dist2) //make sure they are in range
|
||||
continue;
|
||||
|
||||
//Only npcs mgb should hit are client pets...
|
||||
if(curmob->IsNPC())
|
||||
{
|
||||
Mob *owner = curmob->GetOwner();
|
||||
if(owner)
|
||||
{
|
||||
if(!owner->IsClient())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(bad)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
caster->SpellOnTarget(spell_id, curmob);
|
||||
}
|
||||
}
|
||||
|
||||
// solar: causes caster to hit every mob within dist range of center with
|
||||
// a bard pulse of spell_id.
|
||||
// NPC spells will only affect other NPCs with compatible faction
|
||||
void EntityList::AEBardPulse(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster)
|
||||
{
|
||||
LinkedListIterator<Mob*> iterator(mob_list);
|
||||
Mob *curmob;
|
||||
|
||||
float dist = caster->GetAOERange(spell_id);
|
||||
float dist2 = dist * dist;
|
||||
|
||||
bool bad = IsDetrimentalSpell(spell_id);
|
||||
bool isnpc = caster->IsNPC();
|
||||
|
||||
for(iterator.Reset(); iterator.MoreElements(); iterator.Advance())
|
||||
{
|
||||
curmob = iterator.GetData();
|
||||
if(curmob == center) //do not affect center
|
||||
continue;
|
||||
if(curmob == caster && !affect_caster) //watch for caster too
|
||||
continue;
|
||||
if(center->DistNoRoot(*curmob) > dist2) //make sure they are in range
|
||||
continue;
|
||||
if(isnpc && curmob->IsNPC()) { //check npc->npc casting
|
||||
FACTION_VALUE f = curmob->GetReverseFactionCon(caster);
|
||||
if(bad) {
|
||||
//affect mobs that are on our hate list, or
|
||||
//which have bad faction with us
|
||||
if( ! (caster->CheckAggro(curmob) || f == FACTION_THREATENLY || f == FACTION_SCOWLS) )
|
||||
continue;
|
||||
} else {
|
||||
//only affect mobs we would assist.
|
||||
if( ! (f <= FACTION_AMIABLE))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
//finally, make sure they are within range
|
||||
if(bad) {
|
||||
if(!center->CheckLosFN(curmob))
|
||||
continue;
|
||||
}
|
||||
//if we get here... cast the spell.
|
||||
curmob->BardPulse(spell_id, caster);
|
||||
}
|
||||
if(caster->IsClient())
|
||||
caster->CastToClient()->CheckSongSkillIncrease(spell_id);
|
||||
}
|
||||
|
||||
//Dook- Rampage and stuff for clients.
|
||||
//NPCs handle it differently in Mob::Rampage
|
||||
void EntityList::AEAttack(Mob *attacker, float dist, int Hand, int count, bool IsFromSpell) {
|
||||
//Dook- Will need tweaking, currently no pets or players or horses
|
||||
LinkedListIterator<Mob*> iterator(mob_list);
|
||||
Mob *curmob;
|
||||
|
||||
float dist2 = dist * dist;
|
||||
|
||||
int hit = 0;
|
||||
|
||||
for(iterator.Reset(); iterator.MoreElements(); iterator.Advance()) {
|
||||
curmob = iterator.GetData();
|
||||
if(curmob->IsNPC()
|
||||
&& curmob != attacker //this is not needed unless NPCs can use this
|
||||
&&(attacker->IsAttackAllowed(curmob))
|
||||
&& curmob->GetRace() != 216 && curmob->GetRace() != 472 /* dont attack horses */
|
||||
&& (curmob->DistNoRoot(*attacker) <= dist2)
|
||||
) {
|
||||
attacker->Attack(curmob, Hand, false, false, IsFromSpell);
|
||||
hit++;
|
||||
if(count != 0 && hit >= count)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1702
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,156 @@
|
||||
//extends the parser to include perl
|
||||
//Eglin
|
||||
|
||||
#ifndef EMBPARSER_H
|
||||
#define EMBPARSER_H
|
||||
|
||||
#ifdef EMBPERL
|
||||
|
||||
#include "client.h"
|
||||
#include "parser.h"
|
||||
#include "embperl.h"
|
||||
#include "features.h"
|
||||
#include "QuestParserCollection.h"
|
||||
#include "QuestInterface.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
using namespace std;
|
||||
|
||||
class Seperator;
|
||||
|
||||
typedef enum {
|
||||
questDefault = 1,
|
||||
questDefaultByZone,
|
||||
questByName,
|
||||
questTemplate,
|
||||
questTemplateByID,
|
||||
questByID
|
||||
} questMode;
|
||||
|
||||
typedef enum {
|
||||
itemQuestUnloaded = 1,
|
||||
itemQuestScale,
|
||||
itemQuestLore,
|
||||
itemQuestID,
|
||||
itemScriptFileID
|
||||
} itemQuestMode;
|
||||
|
||||
typedef enum {
|
||||
pQuestLoaded = 1,
|
||||
pQuestUnloaded,
|
||||
pQuestEventCast, // player.pl loaded, has an EVENT_CAST sub
|
||||
pQuestReadyToLoad
|
||||
} playerQuestMode;
|
||||
|
||||
typedef enum {
|
||||
nQuestLoaded = 1,
|
||||
nQuestUnloaded,
|
||||
nQuestReadyToLoad
|
||||
} GlobalNPCQuestMode;
|
||||
|
||||
typedef enum {
|
||||
spellQuestUnloaded = 1,
|
||||
spellQuestFullyLoaded,
|
||||
spellQuestFailed
|
||||
} spellQuestMode;
|
||||
|
||||
|
||||
struct EventRecord {
|
||||
QuestEventID event;
|
||||
uint32 objid;
|
||||
string data;
|
||||
NPC* npcmob;
|
||||
ItemInst* iteminst;
|
||||
Mob* mob;
|
||||
uint32 extradata;
|
||||
bool global;
|
||||
};
|
||||
|
||||
class PerlembParser : public Parser
|
||||
{
|
||||
protected:
|
||||
|
||||
//could prolly get rid of this map now, since I check for the
|
||||
//actual subroutine in the quest package as opposed to just seeing
|
||||
//if they do not have a quest or the default.
|
||||
map<uint32, questMode> hasQuests; //npcid -> questMode
|
||||
map<std::string, playerQuestMode> playerQuestLoaded; //zone shortname -> playerQuestMode
|
||||
playerQuestMode globalPlayerQuestLoaded;
|
||||
GlobalNPCQuestMode globalNPCQuestLoaded;
|
||||
map<std::string, itemQuestMode> itemQuestLoaded; // package name - > itemQuestMode
|
||||
map<uint32, spellQuestMode> spellQuestLoaded;
|
||||
|
||||
queue<EventRecord> eventQueue; //for events that happen when perl is in use.
|
||||
bool eventQueueProcessing;
|
||||
|
||||
void HandleQueue();
|
||||
|
||||
void EventCommon(QuestEventID event, uint32 objid, const char * data, NPC* npcmob, ItemInst* iteminst, Mob* mob, uint32 extradata, bool global = false);
|
||||
|
||||
Embperl * perl;
|
||||
//export a symbol table of sorts
|
||||
virtual void map_funs();
|
||||
public:
|
||||
PerlembParser(void);
|
||||
~PerlembParser();
|
||||
Embperl * getperl(void) { return perl; };
|
||||
//todo, consider making the following two methods static (need to check for perl!=null, first, then)
|
||||
bool isloaded(const char *packagename) const;
|
||||
|
||||
//interface stuff
|
||||
virtual void EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data);
|
||||
virtual void EventGlobalNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data);
|
||||
virtual void EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data);
|
||||
virtual void EventGlobalPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data);
|
||||
virtual void EventItem(QuestEventID evt, Client *client, ItemInst *item, uint32 objid, uint32 extra_data);
|
||||
virtual void EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data);
|
||||
|
||||
virtual bool HasQuestSub(uint32 npcid, const char *subname);
|
||||
virtual bool HasGlobalQuestSub(const char *subname);
|
||||
virtual bool PlayerHasQuestSub(const char *subname);
|
||||
virtual bool GlobalPlayerHasQuestSub(const char *subname);
|
||||
virtual bool SpellHasQuestSub(uint32 spell_id, const char *subname);
|
||||
virtual bool ItemHasQuestSub(ItemInst *itm, const char *subname);
|
||||
|
||||
virtual void ReloadQuests(bool with_timers = false);
|
||||
virtual void AddVar(std::string name, std::string val) { Parser::AddVar(name, val); };
|
||||
virtual uint32 GetIdentifier() { return 0xf8b05c11; }
|
||||
|
||||
int LoadScript(int npcid, const char * zone, Mob* activater=0);
|
||||
int LoadGlobalNPCScript();
|
||||
int LoadPlayerScript(const char *zone);
|
||||
int LoadGlobalPlayerScript();
|
||||
int LoadItemScript(ItemInst* iteminst, string packagename, itemQuestMode Qtype);
|
||||
int LoadSpellScript(uint32 id);
|
||||
|
||||
//expose a var to the script (probably parallels addvar))
|
||||
//i.e. exportvar("qst1234", "name", "somemob");
|
||||
//would expose the variable $name='somemob' to the script that handles npc1234
|
||||
void ExportHash(const char *pkgprefix, const char *hashname, std::map<string,string> &vals);
|
||||
void ExportVar(const char * pkgprefix, const char * varname, const char * value) const;
|
||||
void ExportVar(const char * pkgprefix, const char * varname, int value) const;
|
||||
void ExportVar(const char * pkgprefix, const char * varname, unsigned int value) const;
|
||||
void ExportVar(const char * pkgprefix, const char * varname, float value) const;
|
||||
//I don't escape the strings, so use caution!!
|
||||
//Same as export var, except value is not quoted, and is evaluated as perl
|
||||
void ExportVarComplex(const char * pkgprefix, const char * varname, const char * value) const;
|
||||
|
||||
//get an appropriate namespage/packagename from an npcid
|
||||
std::string GetPkgPrefix(uint32 npcid, bool defaultOK = true);
|
||||
//call the appropriate perl handler. afterwards, parse and dispatch the command queue
|
||||
//SendCommands("qst1234", "EVENT_SAY") would trigger sub EVENT_SAY() from the qst1234.pl file
|
||||
virtual void SendCommands(const char * pkgprefix, const char *event, uint32 npcid, Mob* other, Mob* mob, ItemInst* iteminst);
|
||||
|
||||
int HasQuestFile(uint32 npcid);
|
||||
|
||||
#ifdef EMBPERL_COMMANDS
|
||||
void ExecCommand(Client *c, Seperator *sep);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif //EMBPERL
|
||||
|
||||
#endif //EMBPARSER_H
|
||||
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
embperl.cpp
|
||||
---------------
|
||||
wraps a perl interpreter for use in eqemu
|
||||
Eglin
|
||||
*/
|
||||
|
||||
#ifndef EMBPERL_CPP
|
||||
#define EMBPERL_CPP
|
||||
|
||||
#ifdef EMBPERL
|
||||
|
||||
#include "../common/debug.h"
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <vector>
|
||||
#include "embperl.h"
|
||||
#include "embxs.h"
|
||||
#include "features.h"
|
||||
#ifndef GvCV_set
|
||||
#define GvCV_set(gv,cv) (GvCV(gv) = (cv))
|
||||
#endif
|
||||
|
||||
#ifdef EMBPERL_XS
|
||||
EXTERN_C XS(boot_quest);
|
||||
#ifdef EMBPERL_XS_CLASSES
|
||||
EXTERN_C XS(boot_Mob);
|
||||
EXTERN_C XS(boot_NPC);
|
||||
EXTERN_C XS(boot_Client);
|
||||
EXTERN_C XS(boot_Corpse);
|
||||
EXTERN_C XS(boot_EntityList);
|
||||
EXTERN_C XS(boot_Group);
|
||||
EXTERN_C XS(boot_Raid);
|
||||
EXTERN_C XS(boot_QuestItem);
|
||||
EXTERN_C XS(boot_HateEntry);
|
||||
EXTERN_C XS(boot_Object);
|
||||
EXTERN_C XS(boot_Doors);
|
||||
EXTERN_C XS(boot_PerlPacket);
|
||||
/*XS(XS_Client_new);
|
||||
//XS(XS_Mob_new);
|
||||
XS(XS_NPC_new);
|
||||
//XS(XS_Corpse_new);
|
||||
XS(XS_EntityList_new);
|
||||
//XS(XS_Group_new);*/
|
||||
#endif
|
||||
#endif
|
||||
#ifdef EMBPERL_COMMANDS
|
||||
XS(XS_command_add);
|
||||
#endif
|
||||
|
||||
#ifdef EMBPERL_IO_CAPTURE
|
||||
XS(XS_EQEmuIO_PRINT);
|
||||
#endif //EMBPERL_IO_CAPTURE
|
||||
|
||||
//so embedded scripts can use xs extensions (ala 'use socket;')
|
||||
EXTERN_C void boot_DynaLoader(pTHX_ CV* cv);
|
||||
EXTERN_C void xs_init(pTHX)
|
||||
{
|
||||
char file[256];
|
||||
strncpy(file, __FILE__, 256);
|
||||
file[255] = '\0';
|
||||
|
||||
char buf[128]; //shouldent have any function names longer than this.
|
||||
|
||||
//add the strcpy stuff to get rid of const warnings....
|
||||
|
||||
newXS(strcpy(buf, "DynaLoader::boot_DynaLoader"), boot_DynaLoader, file);
|
||||
newXS(strcpy(buf, "quest::boot_qc"), boot_qc, file);
|
||||
#ifdef EMBPERL_XS
|
||||
newXS(strcpy(buf, "quest::boot_quest"), boot_quest, file);
|
||||
#ifdef EMBPERL_XS_CLASSES
|
||||
newXS(strcpy(buf, "Mob::boot_Mob"), boot_Mob, file);
|
||||
newXS(strcpy(buf, "NPC::boot_Mob"), boot_Mob, file);
|
||||
newXS(strcpy(buf, "NPC::boot_NPC"), boot_NPC, file);
|
||||
/// newXS(strcpy(buf, "NPC::new"), XS_NPC_new, file);
|
||||
newXS(strcpy(buf, "Corpse::boot_Mob"), boot_Mob, file);
|
||||
newXS(strcpy(buf, "Corpse::boot_Corpse"), boot_Corpse, file);
|
||||
newXS(strcpy(buf, "Client::boot_Mob"), boot_Mob, file);
|
||||
newXS(strcpy(buf, "Client::boot_Client"), boot_Client, file);
|
||||
// newXS(strcpy(buf, "Client::new"), XS_Client_new, file);
|
||||
newXS(strcpy(buf, "EntityList::boot_EntityList"), boot_EntityList, file);
|
||||
// newXS(strcpy(buf, "EntityList::new"), XS_EntityList_new, file);
|
||||
newXS(strcpy(buf, "PerlPacket::boot_PerlPacket"), boot_PerlPacket, file);
|
||||
newXS(strcpy(buf, "Group::boot_Group"), boot_Group, file);
|
||||
newXS(strcpy(buf, "Raid::boot_Raid"), boot_Raid, file);
|
||||
newXS(strcpy(buf, "QuestItem::boot_QuestItem"), boot_QuestItem, file);
|
||||
newXS(strcpy(buf, "HateEntry::boot_HateEntry"), boot_HateEntry, file);
|
||||
newXS(strcpy(buf, "Object::boot_Object"), boot_Object, file);
|
||||
newXS(strcpy(buf, "Doors::boot_Doors"), boot_Doors, file);
|
||||
;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef EMBPERL_COMMANDS
|
||||
newXS(strcpy(buf, "commands::command_add"), XS_command_add, file);
|
||||
#endif
|
||||
#ifdef EMBPERL_IO_CAPTURE
|
||||
newXS(strcpy(buf, "EQEmuIO::PRINT"), XS_EQEmuIO_PRINT, file);
|
||||
#endif
|
||||
}
|
||||
|
||||
Embperl::Embperl()
|
||||
{
|
||||
in_use = true; //in case one of these files generates an event
|
||||
|
||||
//setup perl...
|
||||
my_perl = perl_alloc();
|
||||
if(!my_perl)
|
||||
throw "Failed to init Perl (perl_alloc)";
|
||||
DoInit();
|
||||
}
|
||||
|
||||
void Embperl::DoInit() {
|
||||
const char *argv_eqemu[] = { "",
|
||||
#ifdef EMBPERL_IO_CAPTURE
|
||||
"-w", "-W",
|
||||
#endif
|
||||
"-e", "0;", NULL };
|
||||
|
||||
int argc = 3;
|
||||
#ifdef EMBPERL_IO_CAPTURE
|
||||
argc = 5;
|
||||
#endif
|
||||
|
||||
char **argv = (char **)argv_eqemu;
|
||||
char **env = { NULL };
|
||||
|
||||
PL_perl_destruct_level = 1;
|
||||
|
||||
perl_construct(my_perl);
|
||||
|
||||
PERL_SYS_INIT3(&argc, &argv, &env);
|
||||
|
||||
perl_parse(my_perl, xs_init, argc, argv, env);
|
||||
|
||||
perl_run(my_perl);
|
||||
|
||||
//a little routine we use a lot.
|
||||
eval_pv("sub my_eval {eval $_[0];}", TRUE); //dies on error
|
||||
|
||||
//ruin the perl exit and command:
|
||||
eval_pv("sub my_exit {}",TRUE);
|
||||
eval_pv("sub my_sleep {}",TRUE);
|
||||
if(gv_stashpv("CORE::GLOBAL", FALSE)) {
|
||||
GV *exitgp = gv_fetchpv("CORE::GLOBAL::exit", TRUE, SVt_PVCV);
|
||||
GvCV_set(exitgp, perl_get_cv("my_exit", TRUE)); //dies on error
|
||||
GvIMPORTED_CV_on(exitgp);
|
||||
GV *sleepgp = gv_fetchpv("CORE::GLOBAL::sleep", TRUE, SVt_PVCV);
|
||||
GvCV_set(sleepgp, perl_get_cv("my_sleep", TRUE)); //dies on error
|
||||
GvIMPORTED_CV_on(sleepgp);
|
||||
}
|
||||
|
||||
//declare our file eval routine.
|
||||
try {
|
||||
init_eval_file();
|
||||
}
|
||||
catch(const char *err)
|
||||
{
|
||||
//remember... lasterr() is no good if we crap out here, in construction
|
||||
LogFile->write(EQEMuLog::Quest, "perl error: %s", err);
|
||||
throw "failed to install eval_file hook";
|
||||
}
|
||||
|
||||
#ifdef EMBPERL_IO_CAPTURE
|
||||
LogFile->write(EQEMuLog::Quest, "Tying perl output to eqemu logs");
|
||||
//make a tieable class to capture IO and pass it into EQEMuLog
|
||||
eval_pv(
|
||||
"package EQEmuIO; "
|
||||
// "&boot_EQEmuIO;"
|
||||
"sub TIEHANDLE { my $me = bless {}, $_[0]; $me->PRINT('Creating '.$me); return($me); } "
|
||||
"sub WRITE { } "
|
||||
//dunno why I need to shift off fmt here, but it dosent like without it
|
||||
"sub PRINTF { my $me = shift; my $fmt = shift; $me->PRINT(sprintf($fmt, @_)); } "
|
||||
"sub CLOSE { my $me = shift; $me->PRINT('Closing '.$me); } "
|
||||
"sub DESTROY { my $me = shift; $me->PRINT('Destroying '.$me); } "
|
||||
//this ties us for all packages, just do it in quest since thats kinda 'our' package
|
||||
"package quest;"
|
||||
" if(tied *STDOUT) { untie(*STDOUT); }"
|
||||
" if(tied *STDERR) { untie(*STDERR); }"
|
||||
" tie *STDOUT, 'EQEmuIO';"
|
||||
" tie *STDERR, 'EQEmuIO';"
|
||||
,FALSE);
|
||||
#endif //EMBPERL_IO_CAPTURE
|
||||
|
||||
#ifdef EMBPERL_PLUGIN
|
||||
eval_pv(
|
||||
"package plugin; "
|
||||
,FALSE
|
||||
);
|
||||
#ifdef EMBPERL_EVAL_COMMANDS
|
||||
try {
|
||||
eval_pv(
|
||||
"use IO::Scalar;"
|
||||
"$plugin::printbuff='';"
|
||||
"tie *PLUGIN,'IO::Scalar',\\$plugin::printbuff;"
|
||||
,FALSE);
|
||||
}
|
||||
catch(const char *err) {
|
||||
throw "failed to install plugin printhook, do you lack IO::Scalar?";
|
||||
}
|
||||
#endif
|
||||
|
||||
LogFile->write(EQEMuLog::Quest, "Loading perlemb plugins.");
|
||||
try
|
||||
{
|
||||
eval_pv("main::eval_file('plugin', 'plugin.pl');", FALSE);
|
||||
}
|
||||
catch(const char *err)
|
||||
{
|
||||
LogFile->write(EQEMuLog::Quest, "Warning - plugin.pl: %s", err);
|
||||
}
|
||||
try
|
||||
{
|
||||
//should probably read the directory in c, instead, so that
|
||||
//I can echo filenames as I do it, but c'mon... I'm lazy and this 1 line reads in all the plugins
|
||||
eval_pv(
|
||||
"if(opendir(D,'plugins')) { "
|
||||
" my @d = readdir(D);"
|
||||
" closedir(D);"
|
||||
" foreach(@d){ "
|
||||
" main::eval_file('plugin','plugins/'.$_)if/\\.pl$/;"
|
||||
" }"
|
||||
"}"
|
||||
,FALSE);
|
||||
}
|
||||
catch(const char *err)
|
||||
{
|
||||
LogFile->write(EQEMuLog::Quest, "Perl warning: %s", err);
|
||||
}
|
||||
#endif //EMBPERL_PLUGIN
|
||||
#ifdef EMBPERL_COMMANDS
|
||||
LogFile->write(EQEMuLog::Quest, "Loading perl commands...");
|
||||
try
|
||||
{
|
||||
eval_pv(
|
||||
"package commands;"
|
||||
"main::eval_file('commands', 'commands.pl');"
|
||||
"&commands::commands_init();"
|
||||
, FALSE);
|
||||
}
|
||||
catch(const char *err)
|
||||
{
|
||||
LogFile->write(EQEMuLog::Quest, "Warning - commands.pl: %s", err);
|
||||
}
|
||||
#endif //EMBPERL_COMMANDS
|
||||
in_use = false;
|
||||
}
|
||||
|
||||
Embperl::~Embperl()
|
||||
{
|
||||
in_use = true;
|
||||
#ifdef EMBPERL_IO_CAPTURE
|
||||
eval_pv(
|
||||
"package quest;"
|
||||
" if(tied *STDOUT) { untie(*STDOUT); }"
|
||||
" if(tied *STDERR) { untie(*STDERR); }"
|
||||
,FALSE);
|
||||
#endif
|
||||
perl_free(my_perl);
|
||||
}
|
||||
|
||||
void Embperl::Reinit() {
|
||||
in_use = true;
|
||||
PL_perl_destruct_level = 1;
|
||||
perl_destruct(my_perl);
|
||||
DoInit();
|
||||
in_use = false;
|
||||
}
|
||||
|
||||
void Embperl::init_eval_file(void)
|
||||
{
|
||||
eval_pv(
|
||||
"our %Cache;"
|
||||
"use Symbol qw(delete_package);"
|
||||
"sub eval_file {"
|
||||
"my($package, $filename) = @_;"
|
||||
"$filename=~s/\'//g;"
|
||||
"if(! -r $filename) { print \"Unable to read perl file '$filename'\\n\"; return; }"
|
||||
"my $mtime = -M $filename;"
|
||||
"if(defined $Cache{$package}{mtime}&&$Cache{$package}{mtime} <= $mtime && !($package eq 'plugin')){"
|
||||
" return;"
|
||||
"} else {"
|
||||
//we 'my' $filename,$mtime,$package,$sub to prevent them from changing our state up here.
|
||||
" eval(\"package $package; my(\\$filename,\\$mtime,\\$package,\\$sub); \\$isloaded = 1; require '$filename'; \");"
|
||||
/* "local *FH;open FH, $filename or die \"open '$filename' $!\";"
|
||||
"local($/) = undef;my $sub = <FH>;close FH;"
|
||||
"my $eval = qq{package $package; sub handler { $sub; }};"
|
||||
"{ my($filename,$mtime,$package,$sub); eval $eval; }"
|
||||
"die $@ if $@;"
|
||||
"$Cache{$package}{mtime} = $mtime; ${$package.'::isloaded'} = 1;}"
|
||||
*/
|
||||
"}"
|
||||
"}"
|
||||
,FALSE);
|
||||
}
|
||||
|
||||
void Embperl::eval_file(const char * packagename, const char * filename)
|
||||
{
|
||||
std::vector<std::string> args;
|
||||
args.push_back(packagename);
|
||||
args.push_back(filename);
|
||||
dosub("eval_file", &args);
|
||||
}
|
||||
|
||||
void Embperl::dosub(const char * subname, const std::vector<std::string> * args, int mode)
|
||||
{//as seen in perlembed docs
|
||||
#if EQDEBUG >= 5
|
||||
if(InUse()) {
|
||||
LogFile->write(EQEMuLog::Debug, "Warning: Perl dosub called for %s when perl is allready in use.\n", subname);
|
||||
}
|
||||
#endif
|
||||
in_use = true;
|
||||
bool err = false;
|
||||
dSP; /* initialize stack pointer */
|
||||
ENTER; /* everything created after here */
|
||||
SAVETMPS; /* ...is a temporary variable. */
|
||||
PUSHMARK(SP); /* remember the stack pointer */
|
||||
if(args && args->size())
|
||||
{
|
||||
for(std::vector<std::string>::const_iterator i = args->begin(); i != args->end(); ++i)
|
||||
{/* push the arguments onto the perl stack */
|
||||
XPUSHs(sv_2mortal(newSVpv(i->c_str(), i->length())));
|
||||
}
|
||||
}
|
||||
PUTBACK; /* make local stack pointer global */
|
||||
call_pv(subname, mode); /*eval our code*/
|
||||
SPAGAIN; /* refresh stack pointer */
|
||||
if(SvTRUE(ERRSV))
|
||||
{
|
||||
err = true;
|
||||
}
|
||||
FREETMPS; /* free temp values */
|
||||
LEAVE; /* ...and the XPUSHed "mortal" args.*/
|
||||
|
||||
in_use = false;
|
||||
if(err)
|
||||
{
|
||||
errmsg = "Perl runtime error: ";
|
||||
errmsg += SvPVX(ERRSV);
|
||||
throw errmsg.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
//evaluate an expression. throw error on fail
|
||||
void Embperl::eval(const char * code)
|
||||
{
|
||||
std::vector<std::string> arg;
|
||||
arg.push_back(code);
|
||||
// MYRA - added EVAL & KEEPERR to eval per Eglin's recommendation
|
||||
dosub("my_eval", &arg, G_SCALAR|G_DISCARD|G_EVAL|G_KEEPERR);
|
||||
//end Myra
|
||||
}
|
||||
|
||||
bool Embperl::SubExists(const char *package, const char *sub) {
|
||||
HV *stash = gv_stashpv(package, false);
|
||||
if(!stash)
|
||||
return(false);
|
||||
int len = strlen(sub);
|
||||
return(hv_exists(stash, sub, len));
|
||||
}
|
||||
|
||||
bool Embperl::VarExists(const char *package, const char *var) {
|
||||
HV *stash = gv_stashpv(package, false);
|
||||
if(!stash)
|
||||
return(false);
|
||||
int len = strlen(var);
|
||||
return(hv_exists(stash, var, len));
|
||||
}
|
||||
|
||||
|
||||
#endif //EMBPERL
|
||||
|
||||
#endif //EMBPERL_CPP
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
Embperl.h
|
||||
---------------
|
||||
eqemu perl wrapper
|
||||
Eglin
|
||||
*/
|
||||
|
||||
#ifndef EMBPERL_H
|
||||
#define EMBPERL_H
|
||||
|
||||
#ifdef EMBPERL
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
//headers from the Perl distribution
|
||||
#include <EXTERN.h>
|
||||
#define WIN32IO_IS_STDIO
|
||||
|
||||
#ifndef WIN32
|
||||
extern "C" { //the perl headers dont do this for us...
|
||||
#endif
|
||||
#include <perl.h>
|
||||
#include <XSUB.h>
|
||||
#ifndef WIN32
|
||||
};
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
//perl defines these macros and dosent clean them up, lazy bastards. -- I hate them too!
|
||||
#ifdef Copy
|
||||
#undef Copy
|
||||
#endif
|
||||
|
||||
#ifdef list
|
||||
#undef list
|
||||
#endif
|
||||
|
||||
#ifdef write
|
||||
#undef write
|
||||
#endif
|
||||
|
||||
#ifdef bool
|
||||
#undef bool
|
||||
#endif
|
||||
|
||||
#ifdef Zero
|
||||
#undef Zero
|
||||
#endif
|
||||
|
||||
//so embedded scripts can use xs extensions (ala 'use socket;')
|
||||
EXTERN_C void boot_DynaLoader(pTHX_ CV* cv);
|
||||
EXTERN_C void xs_init(pTHX);
|
||||
|
||||
class Embperl
|
||||
{
|
||||
private:
|
||||
//if we fail inside a script evaluation, this will hold the croak msg (not much help if we die during construction, but that's our own fault)
|
||||
mutable std::string errmsg;
|
||||
//kludgy workaround for the fact that we can't directly do something like SvIV(get_sv($big[0]{ass}->{struct}))
|
||||
SV * my_get_sv(const char * varname) {
|
||||
char buffer[256];
|
||||
snprintf(buffer, 256, "if(defined(%s)) { $scratch::temp = %s; } else { $scratch::temp = 'UNDEF'; }", varname, varname);
|
||||
eval(buffer);
|
||||
return get_sv("scratch::temp", false);
|
||||
}
|
||||
|
||||
//install a perl func
|
||||
void init_eval_file(void);
|
||||
|
||||
bool in_use; //true if perl is executing
|
||||
protected:
|
||||
//the embedded interpreter
|
||||
PerlInterpreter * my_perl;
|
||||
|
||||
void DoInit();
|
||||
|
||||
public:
|
||||
Embperl(void); //This can throw errors! Buyer beware
|
||||
~Embperl(void);
|
||||
|
||||
void Reinit();
|
||||
|
||||
//return the last error msg
|
||||
std::string lasterr(void) const { return errmsg;};
|
||||
//evaluate an expression. throws string errors on fail
|
||||
void eval(const char * code);
|
||||
//execute a subroutine. throws lasterr on failure
|
||||
void dosub(const char * subname, const std::vector<std::string> * args = NULL, int mode = G_SCALAR|G_DISCARD|G_EVAL);
|
||||
|
||||
//Access to perl variables
|
||||
//all varnames here should be of the form package::name
|
||||
//returns the contents of the perl variable named in varname as a c int
|
||||
int geti(const char * varname) { return SvIV(my_get_sv(varname)); };
|
||||
//returns the contents of the perl variable named in varname as a c float
|
||||
float getd(const char * varname) { return SvNV(my_get_sv(varname));};
|
||||
//returns the contents of the perl variable named in varname as a string
|
||||
std::string getstr(const char * varname) {
|
||||
SV * temp = my_get_sv(varname);
|
||||
return std::string(SvPV_nolen(temp),SvLEN(temp));
|
||||
}
|
||||
|
||||
//put an integer into a perl varable
|
||||
void seti(const char *varname, int val) const {
|
||||
SV *t = get_sv(varname, true);
|
||||
sv_setiv(t, val);
|
||||
}
|
||||
//put a real into a perl varable
|
||||
void setd(const char *varname, float val) const {
|
||||
SV *t = get_sv(varname, true);
|
||||
sv_setnv(t, val);
|
||||
}
|
||||
//put a string into a perl varable
|
||||
void setstr(const char *varname, const char *val) const {
|
||||
SV *t = get_sv(varname, true);
|
||||
sv_setpv(t, val);
|
||||
}
|
||||
|
||||
// put key-value pairs in hash
|
||||
void sethash(const char *varname, std::map<std::string,std::string> &vals)
|
||||
{
|
||||
std::map<std::string,std::string>::iterator it;
|
||||
|
||||
// Get hash and clear it.
|
||||
HV *hv = get_hv(varname, TRUE);
|
||||
hv_clear(hv);
|
||||
|
||||
// Iterate through key-value pairs, storing them in hash
|
||||
for (it = vals.begin(); it != vals.end(); it++)
|
||||
{
|
||||
int keylen = it->first.length();
|
||||
|
||||
SV *val = newSVpv(it->second.c_str(), it->second.length());
|
||||
|
||||
// If val was not added to hash, reset reference count
|
||||
if (hv_store(hv, it->first.c_str(), keylen, val, 0) == NULL)
|
||||
val->sv_refcnt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//loads a file and compiles it into our interpreter (assuming it hasn't already been read in)
|
||||
//idea borrowed from perlembed
|
||||
void eval_file(const char * packagename, const char * filename);
|
||||
|
||||
inline bool InUse() const { return(in_use); }
|
||||
|
||||
//check to see if a sub exists in package
|
||||
bool SubExists(const char *package, const char *sub);
|
||||
|
||||
//check to see if a variable exists in package
|
||||
bool VarExists(const char *package, const char *var);
|
||||
};
|
||||
#endif //EMBPERL
|
||||
|
||||
#endif //EMBPERL_H
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifdef EMBPERL
|
||||
|
||||
#include "../common/debug.h"
|
||||
#include "masterentity.h"
|
||||
#include "command.h"
|
||||
|
||||
#include "embperl.h"
|
||||
#include "embxs.h"
|
||||
|
||||
|
||||
|
||||
const char *getItemName(unsigned itemid)
|
||||
{
|
||||
const Item_Struct* item = NULL;
|
||||
item = database.GetItem(itemid);
|
||||
|
||||
if (item)
|
||||
return item->Name;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
XS(XS_qc_getItemName); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_qc_getItemName)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: quest::getItemName(itemid)");
|
||||
{
|
||||
unsigned itemid = (unsigned)SvUV(ST(0));
|
||||
const char * RETVAL;
|
||||
dXSTARG;
|
||||
RETVAL = getItemName(itemid);
|
||||
sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG;
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
|
||||
EXTERN_C XS(boot_qc); /* prototype to pass -Wmissing-prototypes */
|
||||
EXTERN_C XS(boot_qc)
|
||||
{
|
||||
dXSARGS;
|
||||
char file[256];
|
||||
strncpy(file, __FILE__, 256);
|
||||
file[255] = '\0';
|
||||
|
||||
if(items != 1)
|
||||
LogFile->write(EQEMuLog::Error, "boot_qc does not take any arguments.");
|
||||
|
||||
char buf[128]; //shouldent have any function names longer than this.
|
||||
|
||||
//add the strcpy stuff to get rid of const warnings....
|
||||
|
||||
XS_VERSION_BOOTCHECK ;
|
||||
|
||||
newXS(strcpy(buf, "quest::getItemName"), XS_qc_getItemName, file);
|
||||
|
||||
XSRETURN_YES;
|
||||
}
|
||||
|
||||
#ifdef EMBPERL_IO_CAPTURE
|
||||
|
||||
XS(XS_EQEmuIO_PRINT); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_EQEmuIO_PRINT)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items < 2)
|
||||
return;
|
||||
// Perl_croak(aTHX_ "Usage: EQEmuIO::PRINT(@strings)");
|
||||
|
||||
int r;
|
||||
for(r = 1; r < items; r++) {
|
||||
char *str = SvPV_nolen(ST(r));
|
||||
char *cur = str;
|
||||
|
||||
int i;
|
||||
int pos = 0;
|
||||
int len = 0;
|
||||
for(i = 0; *cur != '\0'; i++, cur++) {
|
||||
if(*cur == '\n') {
|
||||
LogFile->writebuf(EQEMuLog::Quest, str + pos, 1, len);
|
||||
len = 0;
|
||||
pos = i+1;
|
||||
} else {
|
||||
len++;
|
||||
}
|
||||
}
|
||||
if(len > 0) {
|
||||
LogFile->writebuf(EQEMuLog::Quest, str + pos, 1, len);
|
||||
}
|
||||
}
|
||||
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
#endif //EMBPERL_IO_CAPTURE
|
||||
|
||||
|
||||
#ifdef EMBPERL_COMMANDS
|
||||
|
||||
XS(XS_command_add); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_command_add)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 3)
|
||||
Perl_croak(aTHX_ "Usage: commands::command_add(name, desc, access)");
|
||||
|
||||
char *name = SvPV_nolen(ST(0));
|
||||
char *desc = SvPV_nolen(ST(1));
|
||||
int access = (int)SvIV(ST(2));
|
||||
|
||||
command_add_perl(name, desc, access);
|
||||
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
#endif //EMBPERL_COMMANDS
|
||||
|
||||
#endif // EMBPERL
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef EMBXS_H
|
||||
#define EMBXS_H
|
||||
|
||||
//headers from the Perl distribution
|
||||
#include <EXTERN.h>
|
||||
#define WIN32IO_IS_STDIO
|
||||
|
||||
#ifndef WIN32
|
||||
extern "C" { //the perl headers dont do this for us...
|
||||
#endif
|
||||
#include <perl.h>
|
||||
#include <XSUB.h>
|
||||
#ifndef WIN32
|
||||
};
|
||||
#endif
|
||||
|
||||
const char *getItemName(unsigned itemid);
|
||||
XS(XS_qc_getItemName); /* prototype to pass -Wmissing-prototypes */
|
||||
EXTERN_C XS(boot_qc); /* prototype to pass -Wmissing-prototypes */
|
||||
#endif // EMBXS_H
|
||||
+5292
File diff suppressed because it is too large
Load Diff
+467
@@ -0,0 +1,467 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef ENTITY_H
|
||||
#define ENTITY_H
|
||||
|
||||
#include "../common/types.h"
|
||||
#include "../common/linked_list.h"
|
||||
#include "zonedb.h"
|
||||
#include "../common/eq_constants.h"
|
||||
#include "zonedump.h"
|
||||
#include "zonedbasync.h"
|
||||
#include "../common/servertalk.h"
|
||||
#include "../common/bodytypes.h"
|
||||
#include "QGlobals.h"
|
||||
|
||||
// max number of newspawns to send per bulk packet
|
||||
#define SPAWNS_PER_POINT_DATARATE 10
|
||||
#define MAX_SPAWNS_PER_PACKET 100
|
||||
|
||||
//#ifdef _WINDOWS
|
||||
class EQApplicationPacket;
|
||||
//#else
|
||||
// struct EQApplicationPacket;
|
||||
//#endif
|
||||
|
||||
class Client;
|
||||
class Mob;
|
||||
class NPC;
|
||||
class Merc;
|
||||
class Corpse;
|
||||
class Beacon;
|
||||
class Petition;
|
||||
class Object;
|
||||
class Group;
|
||||
class Raid;
|
||||
class Doors;
|
||||
class Trap;
|
||||
class Entity;
|
||||
class EntityList;
|
||||
|
||||
#ifdef BOTS
|
||||
class Bot;
|
||||
class BotRaids;
|
||||
#endif
|
||||
|
||||
extern EntityList entity_list;
|
||||
|
||||
void ProcessClientThreadSpawn(void *tmp);
|
||||
|
||||
class Entity
|
||||
{
|
||||
public:
|
||||
Entity();
|
||||
virtual ~Entity();
|
||||
|
||||
virtual bool IsClient() const { return false; }
|
||||
virtual bool IsNPC() const { return false; }
|
||||
virtual bool IsMob() const { return false; }
|
||||
virtual bool IsMerc() const { return false; }
|
||||
virtual bool IsCorpse() const { return false; }
|
||||
virtual bool IsPlayerCorpse() const { return false; }
|
||||
virtual bool IsNPCCorpse() const { return false; }
|
||||
virtual bool IsObject() const { return false; }
|
||||
// virtual bool IsGroup() const { return false; }
|
||||
virtual bool IsDoor() const { return false; }
|
||||
virtual bool IsTrap() const { return false; }
|
||||
virtual bool IsBeacon() const { return false; }
|
||||
|
||||
virtual bool Process() { return false; }
|
||||
virtual bool Save() { return true; }
|
||||
virtual void Depop(bool StartSpawnTimer = false) {}
|
||||
|
||||
Client* CastToClient();
|
||||
NPC* CastToNPC();
|
||||
Mob* CastToMob();
|
||||
Merc* CastToMerc();
|
||||
Corpse* CastToCorpse();
|
||||
Object* CastToObject();
|
||||
Doors* CastToDoors();
|
||||
Trap* CastToTrap();
|
||||
Beacon* CastToBeacon();
|
||||
|
||||
const Client* CastToClient() const;
|
||||
const NPC* CastToNPC() const;
|
||||
const Mob* CastToMob() const;
|
||||
const Merc* CastToMerc() const;
|
||||
const Corpse* CastToCorpse() const;
|
||||
const Object* CastToObject() const;
|
||||
// const Group* CastToGroup() const;
|
||||
const Doors* CastToDoors() const;
|
||||
const Trap* CastToTrap() const;
|
||||
const Beacon* CastToBeacon() const;
|
||||
|
||||
inline const uint16& GetID() const{ return id; }
|
||||
virtual const char* GetName() { return ""; }
|
||||
virtual void DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) { pDBAsyncWorkID = 0; }
|
||||
bool CheckCoordLosNoZLeaps(float cur_x, float cur_y, float cur_z, float trg_x, float trg_y, float trg_z, float perwalk=1);
|
||||
|
||||
#ifdef BOTS
|
||||
virtual bool IsBot() const { return false; }
|
||||
Bot* CastToBot();
|
||||
#endif
|
||||
|
||||
protected:
|
||||
friend class EntityList;
|
||||
virtual void SetID(uint16 set_id);
|
||||
uint32 pDBAsyncWorkID;
|
||||
private:
|
||||
uint16 id;
|
||||
};
|
||||
|
||||
class EntityList
|
||||
{
|
||||
public:
|
||||
EntityList();
|
||||
~EntityList();
|
||||
|
||||
Entity* GetID(uint16 id);
|
||||
Mob* GetMob(uint16 id);
|
||||
inline Mob* GetMobID(uint16 id) { return(GetMob(id)); } //for perl
|
||||
Mob* GetMob(const char* name);
|
||||
Mob* GetMobByNpcTypeID(uint32 get_id);
|
||||
Mob* GetTargetForVirus(Mob* spreader);
|
||||
NPC* GetNPCByID(uint16 id);
|
||||
NPC* GetNPCByNPCTypeID(uint32 npc_id);
|
||||
Merc* GetMercByID(uint16 id);
|
||||
Client* GetClientByName(const char *name);
|
||||
Client* GetClientByAccID(uint32 accid);
|
||||
Client* GetClientByID(uint16 id);
|
||||
Client* GetClientByCharID(uint32 iCharID);
|
||||
Client* GetClientByWID(uint32 iWID);
|
||||
Client* GetClient(uint32 ip, uint16 port);
|
||||
Client* GetRandomClient(float x, float y, float z, float Distance, Client *ExcludeClient = NULL);
|
||||
Group* GetGroupByMob(Mob* mob);
|
||||
Group* GetGroupByClient(Client* client);
|
||||
Group* GetGroupByID(uint32 id);
|
||||
Group* GetGroupByLeaderName(char* leader);
|
||||
Raid* GetRaidByMob(Mob* mob);
|
||||
Raid* GetRaidByClient(Client* client);
|
||||
Raid* GetRaidByID(uint32 id);
|
||||
Raid* GetRaidByLeaderName(const char *leader);
|
||||
|
||||
Corpse* GetCorpseByOwner(Client* client);
|
||||
Corpse* GetCorpseByID(uint16 id);
|
||||
Corpse* GetCorpseByDBID(uint32 dbid);
|
||||
Corpse* GetCorpseByName(const char* name);
|
||||
|
||||
Client* FindCorpseDragger(const char *CorpseName);
|
||||
|
||||
Object* GetObjectByID(uint16 id);
|
||||
Object* GetObjectByDBID(uint32 id);
|
||||
Doors* GetDoorsByID(uint16 id);
|
||||
Doors* GetDoorsByDoorID(uint32 id);
|
||||
Doors* GetDoorsByDBID(uint32 id);
|
||||
void RemoveAllCorpsesByCharID(uint32 charid);
|
||||
void RemoveCorpseByDBID(uint32 dbid);
|
||||
int RezzAllCorpsesByCharID(uint32 charid);
|
||||
bool IsMobInZone(Mob *who);
|
||||
void ClearClientPetitionQueue();
|
||||
bool CanAddHateForMob(Mob *p);
|
||||
void SendGuildMOTD(uint32 guild_id);
|
||||
void SendGuildSpawnAppearance(uint32 guild_id);
|
||||
void SendGuildMembers(uint32 guild_id);
|
||||
void RefreshAllGuildInfo(uint32 guild_id);
|
||||
void SendGuildList();
|
||||
// void SendGuildJoin(GuildJoin_Struct* gj);
|
||||
// Check group list for NULL entries
|
||||
void CheckGroupList (const char *fname, const int fline);
|
||||
void GroupProcess();
|
||||
void RaidProcess();
|
||||
void DoorProcess();
|
||||
void ObjectProcess();
|
||||
void CorpseProcess();
|
||||
void MobProcess();
|
||||
void TrapProcess();
|
||||
void BeaconProcess();
|
||||
void ProcessMove(Client *c, float x, float y, float z);
|
||||
void ProcessProximitySay(const char *Message, Client *c, uint8 language = 0);
|
||||
void SendAATimer(uint32 charid,UseAA_Struct* uaa);
|
||||
Doors* FindDoor(uint8 door_id);
|
||||
Object* FindObject(uint32 object_id);
|
||||
Object* FindNearbyObject(float x, float y, float z, float radius);
|
||||
bool MakeDoorSpawnPacket(EQApplicationPacket* app, Client *client);
|
||||
bool MakeTrackPacket(Client* client);
|
||||
void SendTraders(Client* client);
|
||||
void AddClient(Client*);
|
||||
void AddNPC(NPC*, bool SendSpawnPacket = true, bool dontqueue = false);
|
||||
void AddMerc(Merc*, bool SendSpawnPacket = true, bool dontqueue = false);
|
||||
void AddCorpse(Corpse* pc, uint32 in_id = 0xFFFFFFFF);
|
||||
void AddObject(Object*, bool SendSpawnPacket = true);
|
||||
void AddGroup(Group*);
|
||||
void AddGroup(Group*, uint32 id);
|
||||
void AddRaid(Raid *raid);
|
||||
void AddRaid(Raid*, uint32 id);
|
||||
void AddDoor(Doors* door);
|
||||
void AddTrap(Trap* trap);
|
||||
void AddBeacon(Beacon *beacon);
|
||||
void AddProximity(NPC *proximity_for);
|
||||
void Clear();
|
||||
bool RemoveMob(uint16 delete_id);
|
||||
bool RemoveMob(Mob* delete_mob);
|
||||
bool RemoveClient(uint16 delete_id);
|
||||
bool RemoveClient(Client* delete_client);
|
||||
bool RemoveNPC(uint16 delete_id);
|
||||
bool RemoveMerc(uint16 delete_id);
|
||||
bool RemoveGroup(uint32 delete_id);
|
||||
bool RemoveRaid(uint32 delete_id);
|
||||
bool RemoveCorpse(uint16 delete_id);
|
||||
bool RemoveDoor(uint16 delete_id);
|
||||
bool RemoveTrap(uint16 delete_id);
|
||||
bool RemoveObject(uint16 delete_id);
|
||||
bool RemoveProximity(uint16 delete_npc_id);
|
||||
void RemoveAllMobs();
|
||||
void RemoveAllClients();
|
||||
void RemoveAllNPCs();
|
||||
void RemoveAllMercs();
|
||||
void RemoveAllGroups();
|
||||
void RemoveAllCorpses();
|
||||
void RemoveAllDoors();
|
||||
void DespawnAllDoors();
|
||||
void RespawnAllDoors();
|
||||
void RemoveAllTraps();
|
||||
void RemoveAllObjects();
|
||||
void RemoveAllLocalities();
|
||||
void RemoveAllRaids();
|
||||
void DestroyTempPets(Mob *owner);
|
||||
Entity* GetEntityMob(uint16 id);
|
||||
Entity* GetEntityMob(const char *name);
|
||||
Entity* GetEntityMerc(uint16 id);
|
||||
Entity* GetEntityDoor(uint16 id);
|
||||
Entity* GetEntityObject(uint16 id);
|
||||
Entity* GetEntityCorpse(uint16 id);
|
||||
Entity* GetEntityCorpse(const char *name);
|
||||
// Entity* GetEntityGroup(uint32 id);
|
||||
Entity* GetEntityTrap(uint16 id);
|
||||
Entity* GetEntityBeacon(uint16 id);
|
||||
|
||||
void DescribeAggro(Client *towho, NPC *from_who, float dist, bool verbose);
|
||||
|
||||
void Message(uint32 to_guilddbid, uint32 type, const char* message, ...);
|
||||
void MessageStatus(uint32 to_guilddbid, int to_minstatus, uint32 type, const char* message, ...);
|
||||
void MessageClose(Mob* sender, bool skipsender, float dist, uint32 type, const char* message, ...);
|
||||
void Message_StringID(Mob *sender, bool skipsender, uint32 type, uint32 string_id, const char* message1=0,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0);
|
||||
void MessageClose_StringID(Mob *sender, bool skipsender, float dist, uint32 type, uint32 string_id, const char* message1=0,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0);
|
||||
void ChannelMessageFromWorld(const char* from, const char* to, uint8 chan_num, uint32 guilddbid, uint8 language, const char* message);
|
||||
void ChannelMessage(Mob* from, uint8 chan_num, uint8 language, const char* message, ...);
|
||||
void ChannelMessage(Mob* from, uint8 chan_num, uint8 language, uint8 lang_skill, const char* message, ...);
|
||||
void ChannelMessageSend(Mob* to, uint8 chan_num, uint8 language, const char* message, ...);
|
||||
void SendZoneSpawns(Client*);
|
||||
void SendZonePVPUpdates(Client *);
|
||||
void SendZoneSpawnsBulk(Client* client);
|
||||
void Save();
|
||||
void SendZoneCorpses(Client*);
|
||||
void SendZoneCorpsesBulk(Client*);
|
||||
void SendZoneObjects(Client* client);
|
||||
void SendZoneAppearance(Client *c);
|
||||
void SendNimbusEffects(Client *c);
|
||||
void SendUntargetable(Client *c);
|
||||
void DuelMessage(Mob* winner, Mob* loser, bool flee);
|
||||
void QuestJournalledSayClose(Mob *sender, Client *QuestIntiator, float dist, const char* mobname, const char* message);
|
||||
void GroupMessage(uint32 gid, const char *from, const char *message);
|
||||
void ExpeditionWarning(uint32 minutes_left);
|
||||
|
||||
void RemoveFromTargets(Mob* mob, bool RemoveFromXTargets = false);
|
||||
void RemoveFromXTargets(Mob* mob);
|
||||
void RemoveFromAutoXTargets(Mob* mob);
|
||||
void ReplaceWithTarget(Mob* pOldMob, Mob*pNewTarget);
|
||||
void QueueCloseClients(Mob* sender, const EQApplicationPacket* app, bool ignore_sender=false, float dist=200, Mob* SkipThisMob = 0, bool ackreq = true,eqFilterType filter=FilterNone);
|
||||
void QueueClients(Mob* sender, const EQApplicationPacket* app, bool ignore_sender=false, bool ackreq = true);
|
||||
void QueueClientsStatus(Mob* sender, const EQApplicationPacket* app, bool ignore_sender = false, uint8 minstatus = 0, uint8 maxstatus = 0);
|
||||
void QueueClientsGuild(Mob* sender, const EQApplicationPacket* app, bool ignore_sender = false, uint32 guildeqid = 0);
|
||||
void QueueClientsGuildBankItemUpdate(const GuildBankItemUpdate_Struct *gbius, uint32 GuildID);
|
||||
void QueueClientsByTarget(Mob* sender, const EQApplicationPacket* app, bool iSendToSender = true, Mob* SkipThisMob = 0, bool ackreq = true,
|
||||
bool HoTT = true, uint32 ClientVersionBits = 0xFFFFFFFF);
|
||||
|
||||
void QueueClientsByXTarget(Mob* sender, const EQApplicationPacket* app, bool iSendToSender = true);
|
||||
void QueueToGroupsForNPCHealthAA(Mob* sender, const EQApplicationPacket* app);
|
||||
void QueueManaged(Mob* sender, const EQApplicationPacket* app, bool ignore_sender=false, bool ackreq = true);
|
||||
|
||||
void AEAttack(Mob *attacker, float dist, int Hand = 13, int count = 0, bool IsFromSpell = false);
|
||||
void AETaunt(Client *caster, float range = 0);
|
||||
void AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true, int16 resist_adjust = 0);
|
||||
void MassGroupBuff(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true);
|
||||
void AEBardPulse(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true);
|
||||
|
||||
void RadialSetLogging(Mob *around, bool enabled, bool clients, bool non_clients, float range = 0);
|
||||
|
||||
//trap stuff
|
||||
Mob* GetTrapTrigger(Trap* trap);
|
||||
void SendAlarm(Trap* trap, Mob* currenttarget, uint8 kos);
|
||||
Trap* FindNearbyTrap(Mob* searcher, float max_dist);
|
||||
|
||||
void AddHealAggro(Mob* target, Mob* caster, uint16 thedam);
|
||||
Mob* FindDefenseNPC(uint32 npcid);
|
||||
void OpenDoorsNear(NPC* opener);
|
||||
void UpdateWho(bool iSendFullUpdate = false);
|
||||
void SendPositionUpdates(Client* client, uint32 cLastUpdate = 0, float range = 0, Entity* alwayssend = 0, bool iSendEvenIfNotChanged = false);
|
||||
char* MakeNameUnique(char* name);
|
||||
static char* RemoveNumbers(char* name);
|
||||
void SignalMobsByNPCID(uint32 npc_type, int signal_id);
|
||||
void CountNPC(uint32* NPCCount, uint32* NPCLootCount, uint32* gmspawntype_count);
|
||||
void DoZoneDump(ZSDump_Spawn2* spawn2dump, ZSDump_NPC* npcdump, ZSDump_NPC_Loot* npclootdump, NPCType* gmspawntype_dump);
|
||||
void RemoveEntity(uint16 id);
|
||||
void SendPetitionToAdmins(Petition* pet);
|
||||
void SendPetitionToAdmins();
|
||||
void AddLootToNPCS(uint32 item_id, uint32 count);
|
||||
|
||||
void ListNPCs(Client* client, const char* arg1 = 0, const char* arg2 = 0, uint8 searchtype = 0);
|
||||
void ListNPCCorpses(Client* client);
|
||||
void ListPlayerCorpses(Client* client);
|
||||
void FindPathsToAllNPCs();
|
||||
int32 DeleteNPCCorpses();
|
||||
int32 DeletePlayerCorpses();
|
||||
void WriteEntityIDs();
|
||||
void HalveAggro(Mob* who);
|
||||
void DoubleAggro(Mob* who);
|
||||
void Evade(Mob *who);
|
||||
void UpdateHoTT(Mob* target);
|
||||
|
||||
void Process();
|
||||
void ClearAggro(Mob* targ);
|
||||
void ClearFeignAggro(Mob* targ);
|
||||
void ClearZoneFeignAggro(Client* targ);
|
||||
void AggroZone(Mob* who, int hate = 0);
|
||||
|
||||
bool Fighting(Mob* targ);
|
||||
void RemoveFromHateLists(Mob* mob, bool settoone = false);
|
||||
void RemoveDebuffs(Mob* caster);
|
||||
|
||||
|
||||
void MessageGroup(Mob* sender, bool skipclose, uint32 type, const char* message, ...);
|
||||
|
||||
void LimitAddNPC(NPC *npc);
|
||||
void LimitRemoveNPC(NPC *npc);
|
||||
bool LimitCheckType(uint32 npc_type, int count);
|
||||
bool LimitCheckGroup(uint32 spawngroup_id, int count);
|
||||
bool LimitCheckBoth(uint32 npc_type, uint32 spawngroup_id, int group_count, int type_count);
|
||||
bool LimitCheckName(const char* npc_name);
|
||||
|
||||
void CheckClientAggro(Client *around);
|
||||
Mob* AICheckCloseAggro(Mob* sender, float iAggroRange, float iAssistRange);
|
||||
int GetHatedCount(Mob *attacker, Mob *exclude);
|
||||
void AIYellForHelp(Mob* sender, Mob* attacker);
|
||||
bool AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float iRange, uint16 iSpellTypes);
|
||||
bool Merc_AICheckCloseBeneficialSpells(Merc* caster, uint8 iChance, float iRange, uint16 iSpellTypes);
|
||||
Mob* GetTargetForMez(Mob* caster);
|
||||
uint32 CheckNPCsClose(Mob *center);
|
||||
|
||||
Corpse* GetClosestCorpse(Mob* sender, const char *Name);
|
||||
NPC* GetClosestBanker(Mob* sender, uint32 &distance);
|
||||
void CameraEffect(uint32 duration, uint32 intensity);
|
||||
Mob* GetClosestMobByBodyType(Mob* sender, bodyType BodyType);
|
||||
void ForceGroupUpdate(uint32 gid);
|
||||
void SendGroupLeave(uint32 gid, const char *name);
|
||||
void SendGroupJoin(uint32 gid, const char *name);
|
||||
|
||||
void SaveAllClientsTaskState();
|
||||
void ReloadAllClientsTaskState(int TaskID=0);
|
||||
|
||||
uint16 CreateGroundObject(uint32 itemid, float x, float y, float z, float heading, uint32 decay_time = 300000);
|
||||
uint16 CreateGroundObjectFromModel(const char *model, float x, float y, float z, float heading, uint8 type = 0x00, uint32 decay_time = 0);
|
||||
uint16 CreateDoor(const char *model, float x, float y, float z, float heading, uint8 type = 0, uint16 size = 100);
|
||||
void ZoneWho(Client *c, Who_All_Struct* Who);
|
||||
void UnMarkNPC(uint16 ID);
|
||||
|
||||
void GateAllClients();
|
||||
void SignalAllClients(uint32 data);
|
||||
void UpdateQGlobal(uint32 qid, QGlobal newGlobal);
|
||||
void DeleteQGlobal(std::string name, uint32 npcID, uint32 charID, uint32 zoneID);
|
||||
void SendFindableNPCList(Client *c);
|
||||
void UpdateFindableNPCState(NPC *n, bool Remove);
|
||||
void HideCorpses(Client *c, uint8 CurrentMode, uint8 NewMode);
|
||||
|
||||
void GetMobList(list<Mob*> &m_list);
|
||||
void GetNPCList(list<NPC*> &n_list);
|
||||
void GetMercList(list<Merc*> &n_list);
|
||||
void GetClientList(list<Client*> &c_list);
|
||||
void GetCorpseList(list<Corpse*> &c_list);
|
||||
void GetObjectList(list<Object*> &o_list);
|
||||
void GetDoorsList(list<Doors*> &d_list);
|
||||
void GetTargetsForConeArea(Mob *start, uint32 radius, uint32 height, list<Mob*> &m_list);
|
||||
|
||||
void DepopAll(int NPCTypeID, bool StartSpawnTimer = true);
|
||||
|
||||
uint16 GetFreeID();
|
||||
void RefreshAutoXTargets(Client *c);
|
||||
void RefreshClientXTargets(Client *c);
|
||||
|
||||
protected:
|
||||
friend class Zone;
|
||||
void Depop(bool StartSpawnTimer = false);
|
||||
|
||||
private:
|
||||
void AddToSpawnQueue(uint16 entityid, NewSpawn_Struct** app);
|
||||
void CheckSpawnQueue();
|
||||
|
||||
//used for limiting spawns
|
||||
class SpawnLimitRecord { public: uint32 spawngroup_id; uint32 npc_type; };
|
||||
map<uint16, SpawnLimitRecord> npc_limit_list; //entity id -> npc type
|
||||
|
||||
uint32 tsFirstSpawnOnQueue; // timestamp that the top spawn on the spawnqueue was added, should be 0xFFFFFFFF if queue is empty
|
||||
uint32 NumSpawnsOnQueue;
|
||||
LinkedList<NewSpawn_Struct*> SpawnQueue;
|
||||
|
||||
LinkedList<Client*> client_list;
|
||||
LinkedList<Mob*> mob_list;
|
||||
LinkedList<NPC*> npc_list;
|
||||
LinkedList<Merc *> merc_list;
|
||||
list<Group*> group_list;
|
||||
LinkedList<Corpse*> corpse_list;
|
||||
LinkedList<Object*> object_list;
|
||||
LinkedList<Doors*> door_list;
|
||||
LinkedList<Trap*> trap_list;
|
||||
LinkedList<Beacon*> beacon_list;
|
||||
LinkedList<NPC *> proximity_list;
|
||||
list<Raid *> raid_list;
|
||||
uint16 last_insert_id;
|
||||
|
||||
// Please Do Not Declare Any EntityList Class Members After This Comment
|
||||
#ifdef BOTS
|
||||
public:
|
||||
void AddBot(Bot* newBot, bool SendSpawnPacket = true, bool dontqueue = false);
|
||||
void BotPickLock(Bot* rogue);
|
||||
bool RemoveBot(uint16 entityID);
|
||||
Mob* GetMobByBotID(uint32 botID);
|
||||
Bot* GetBotByBotID(uint32 botID);
|
||||
Bot* GetBotByBotName(std::string botName);
|
||||
list<Bot*> GetBotsByBotOwnerCharacterID(uint32 botOwnerCharacterID);
|
||||
|
||||
bool Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, float iRange, uint16 iSpellTypes); // TODO: Evaluate this closesly in hopes to eliminate
|
||||
void ShowSpawnWindow(Client* client, int Distance, bool NamedOnly); // TODO: Implement ShowSpawnWindow in the bot class but it needs entity list stuff
|
||||
private:
|
||||
std::list<Bot*> bot_list;
|
||||
#endif
|
||||
};
|
||||
|
||||
class BulkZoneSpawnPacket {
|
||||
public:
|
||||
BulkZoneSpawnPacket(Client* iSendTo, uint32 iMaxSpawnsPerPacket); // 0 = send zonewide
|
||||
virtual ~BulkZoneSpawnPacket();
|
||||
|
||||
bool AddSpawn(NewSpawn_Struct* ns);
|
||||
void SendBuffer(); // Sends the buffer and cleans up everything - can safely re-use the object after this function call (no need to free and do another new)
|
||||
private:
|
||||
uint32 pMaxSpawnsPerPacket;
|
||||
uint32 index;
|
||||
NewSpawn_Struct* data;
|
||||
Client* pSendTo;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
MA 02111-1307, USA */
|
||||
|
||||
/* Error messages for mysql clients */
|
||||
/* error messages for the demon is in share/language/errmsg.sys */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void init_client_errs(void);
|
||||
extern const char *client_errors[]; /* Error messages */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define CR_MIN_ERROR 2000 /* For easier client code */
|
||||
#define CR_MAX_ERROR 2999
|
||||
#if defined(OS2) && defined( MYSQL_SERVER)
|
||||
#define CER(X) client_errors[(X)-CR_MIN_ERROR]
|
||||
#else
|
||||
#define ER(X) client_errors[(X)-CR_MIN_ERROR]
|
||||
#endif
|
||||
#define CLIENT_ERRMAP 2 /* Errormap used by my_error() */
|
||||
|
||||
#define CR_UNKNOWN_ERROR 2000
|
||||
#define CR_SOCKET_CREATE_ERROR 2001
|
||||
#define CR_CONNECTION_ERROR 2002
|
||||
#define CR_CONN_HOST_ERROR 2003
|
||||
#define CR_IPSOCK_ERROR 2004
|
||||
#define CR_UNKNOWN_HOST 2005
|
||||
#define CR_SERVER_GONE_ERROR 2006
|
||||
#define CR_VERSION_ERROR 2007
|
||||
#define CR_OUT_OF_MEMORY 2008
|
||||
#define CR_WRONG_HOST_INFO 2009
|
||||
#define CR_LOCALHOST_CONNECTION 2010
|
||||
#define CR_TCP_CONNECTION 2011
|
||||
#define CR_SERVER_HANDSHAKE_ERR 2012
|
||||
#define CR_SERVER_LOST 2013
|
||||
#define CR_COMMANDS_OUT_OF_SYNC 2014
|
||||
#define CR_NAMEDPIPE_CONNECTION 2015
|
||||
#define CR_NAMEDPIPEWAIT_ERROR 2016
|
||||
#define CR_NAMEDPIPEOPEN_ERROR 2017
|
||||
#define CR_NAMEDPIPESETSTATE_ERROR 2018
|
||||
#define CR_CANT_READ_CHARSET 2019
|
||||
#define CR_NET_PACKET_TOO_LARGE 2020
|
||||
@@ -0,0 +1,68 @@
|
||||
#ifndef EVENT_CODES_H
|
||||
#define EVENT_CODES_H
|
||||
|
||||
typedef enum {
|
||||
EVENT_SAY = 0,
|
||||
EVENT_ITEM, //being given an item
|
||||
EVENT_DEATH, //being killed
|
||||
EVENT_SPAWN, //triggered when we first spawn
|
||||
EVENT_ATTACK, //being attacked (resets after an interval of not being attacked)
|
||||
EVENT_COMBAT, //being attacked or attacking (resets after an interval of not being attacked)
|
||||
EVENT_AGGRO, //entering combat mode due to a PC attack
|
||||
EVENT_SLAY, //killing a PC
|
||||
EVENT_NPC_SLAY, //killing an NPC
|
||||
EVENT_WAYPOINT_ARRIVE, // reaching a waypoint on a grid
|
||||
EVENT_WAYPOINT_DEPART, // departing a waypoint on a grid
|
||||
EVENT_TIMER,
|
||||
EVENT_SIGNAL,
|
||||
EVENT_HP,
|
||||
EVENT_ENTER, //PC entering your set proximity
|
||||
EVENT_EXIT, //PC leaving your set proximity
|
||||
EVENT_ENTERZONE, //PC only, you enter zone
|
||||
EVENT_CLICKDOOR, //pc only, you click a door
|
||||
EVENT_LOOT, //pc only
|
||||
EVENT_ZONE, //pc only
|
||||
EVENT_LEVEL_UP, //pc only
|
||||
EVENT_KILLED_MERIT, //killed by a PC or group, gave experience; will repeat several times for groups
|
||||
EVENT_CAST_ON, //pc casted a spell on npc
|
||||
EVENT_TASKACCEPTED, //pc accepted a task
|
||||
EVENT_TASK_STAGE_COMPLETE,
|
||||
EVENT_TASK_UPDATE,
|
||||
EVENT_TASK_COMPLETE,
|
||||
EVENT_TASK_FAIL,
|
||||
EVENT_AGGRO_SAY,
|
||||
EVENT_PLAYER_PICKUP,
|
||||
EVENT_POPUPRESPONSE,
|
||||
EVENT_PROXIMITY_SAY,
|
||||
EVENT_CAST,
|
||||
EVENT_SCALE_CALC,
|
||||
EVENT_ITEM_ENTERZONE,
|
||||
EVENT_TARGET_CHANGE, //target selected, target changed, or target removed
|
||||
EVENT_HATE_LIST,
|
||||
EVENT_SPELL_EFFECT_CLIENT,
|
||||
EVENT_SPELL_EFFECT_NPC,
|
||||
EVENT_SPELL_EFFECT_BUFF_TIC_CLIENT,
|
||||
EVENT_SPELL_EFFECT_BUFF_TIC_NPC,
|
||||
EVENT_SPELL_EFFECT_TRANSLOCATE_COMPLETE,
|
||||
EVENT_COMBINE_SUCCESS, //PC successfully combined a recipe
|
||||
EVENT_COMBINE_FAILURE, //PC failed to combine a recipe
|
||||
EVENT_ITEM_CLICK, //SoF+ Item Right Clicked from worn or main/top inventory slot
|
||||
EVENT_ITEM_CLICK_CAST,
|
||||
EVENT_GROUP_CHANGE,
|
||||
EVENT_FORAGE_SUCCESS,
|
||||
EVENT_FORAGE_FAILURE,
|
||||
EVENT_FISH_START,
|
||||
EVENT_FISH_SUCCESS,
|
||||
EVENT_FISH_FAILURE,
|
||||
EVENT_CLICK_OBJECT,
|
||||
EVENT_DISCOVER_ITEM,
|
||||
EVENT_DISCONNECT,
|
||||
EVENT_CONNECT,
|
||||
|
||||
_LargestEventID
|
||||
} QuestEventID;
|
||||
|
||||
extern const char *QuestEventSubroutines[_LargestEventID];
|
||||
|
||||
#endif
|
||||
|
||||
+668
@@ -0,0 +1,668 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "../common/debug.h"
|
||||
#include "features.h"
|
||||
#include "masterentity.h"
|
||||
#include "StringIDs.h"
|
||||
#include "../common/MiscFunctions.h"
|
||||
#include "../common/rulesys.h"
|
||||
#include "QuestParserCollection.h"
|
||||
|
||||
|
||||
static uint32 MaxBankedGroupLeadershipPoints(int Level)
|
||||
{
|
||||
if(Level < 35)
|
||||
return 4;
|
||||
|
||||
if(Level < 51)
|
||||
return 6;
|
||||
|
||||
return 8;
|
||||
}
|
||||
|
||||
static uint32 MaxBankedRaidLeadershipPoints(int Level)
|
||||
{
|
||||
if(Level < 45)
|
||||
return 6;
|
||||
|
||||
if(Level < 55)
|
||||
return 8;
|
||||
|
||||
return 10;
|
||||
}
|
||||
|
||||
void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) {
|
||||
|
||||
uint32 add_exp = in_add_exp;
|
||||
|
||||
if(!resexp && (XPRate != 0))
|
||||
add_exp = static_cast<uint32>(in_add_exp * (static_cast<float>(XPRate) / 100.0f));
|
||||
|
||||
if (m_epp.perAA<0 || m_epp.perAA>100)
|
||||
m_epp.perAA=0; // stop exploit with sanity check
|
||||
|
||||
uint32 add_aaxp;
|
||||
if(resexp) {
|
||||
add_aaxp = 0;
|
||||
} else {
|
||||
|
||||
//figure out how much of this goes to AAs
|
||||
add_aaxp = add_exp * m_epp.perAA / 100;
|
||||
//take that ammount away from regular exp
|
||||
add_exp -= add_aaxp;
|
||||
|
||||
float totalmod = 1.0;
|
||||
float zemmod = 1.0;
|
||||
//get modifiers
|
||||
if(RuleR(Character, ExpMultiplier) >= 0){
|
||||
totalmod *= RuleR(Character, ExpMultiplier);
|
||||
}
|
||||
|
||||
if(zone->newzone_data.zone_exp_multiplier >= 0){
|
||||
zemmod *= zone->newzone_data.zone_exp_multiplier;
|
||||
}
|
||||
|
||||
if(RuleB(Character,UseRaceClassExpBonuses))
|
||||
{
|
||||
if(GetBaseRace() == HALFLING){
|
||||
totalmod *= 1.05;
|
||||
}
|
||||
|
||||
if(GetClass() == ROGUE || GetClass() == WARRIOR){
|
||||
totalmod *= 1.05;
|
||||
}
|
||||
}
|
||||
|
||||
if(zone->IsHotzone())
|
||||
{
|
||||
totalmod += RuleR(Zone, HotZoneBonus);
|
||||
}
|
||||
|
||||
add_exp = uint32(float(add_exp) * totalmod * zemmod);
|
||||
|
||||
if(RuleB(Character,UseXPConScaling))
|
||||
{
|
||||
if (conlevel != 0xFF && !resexp) {
|
||||
switch (conlevel)
|
||||
{
|
||||
case CON_GREEN:
|
||||
add_exp = 0;
|
||||
add_aaxp = 0;
|
||||
return;
|
||||
case CON_LIGHTBLUE:
|
||||
add_exp = add_exp * RuleI(Character, LightBlueModifier)/100;
|
||||
add_aaxp = add_aaxp * RuleI(Character, LightBlueModifier)/100;
|
||||
break;
|
||||
case CON_BLUE:
|
||||
add_exp = add_exp * RuleI(Character, BlueModifier)/100;
|
||||
add_aaxp = add_aaxp * RuleI(Character, BlueModifier)/100;
|
||||
break;
|
||||
case CON_WHITE:
|
||||
add_exp = add_exp * RuleI(Character, WhiteModifier)/100;
|
||||
add_aaxp = add_aaxp * RuleI(Character, WhiteModifier)/100;
|
||||
break;
|
||||
case CON_YELLOW:
|
||||
add_exp = add_exp * RuleI(Character, YellowModifier)/100;
|
||||
add_aaxp = add_aaxp * RuleI(Character, YellowModifier)/100;
|
||||
break;
|
||||
case CON_RED:
|
||||
add_exp = add_exp * RuleI(Character, RedModifier)/100;
|
||||
add_aaxp = add_aaxp * RuleI(Character, RedModifier)/100;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(IsLeadershipEXPOn() && ((conlevel == CON_BLUE) || (conlevel == CON_WHITE) || (conlevel == CON_YELLOW) || (conlevel == CON_RED))) {
|
||||
add_exp = static_cast<uint32>(static_cast<float>(add_exp) * 0.8f);
|
||||
|
||||
if(GetGroup())
|
||||
{
|
||||
if((m_pp.group_leadership_points < MaxBankedGroupLeadershipPoints(GetLevel()))
|
||||
&& (RuleI(Character, KillsPerGroupLeadershipAA) > 0))
|
||||
{
|
||||
AddLeadershipEXP(GROUP_EXP_PER_POINT / RuleI(Character, KillsPerGroupLeadershipAA), 0);
|
||||
Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP);
|
||||
}
|
||||
else
|
||||
Message_StringID(MT_Leadership, MAX_GROUP_LEADERSHIP_POINTS);
|
||||
}
|
||||
else
|
||||
{
|
||||
if((m_pp.raid_leadership_points < MaxBankedRaidLeadershipPoints(GetLevel()))
|
||||
&& (RuleI(Character, KillsPerRaidLeadershipAA) > 0))
|
||||
{
|
||||
AddLeadershipEXP(0, RAID_EXP_PER_POINT / RuleI(Character, KillsPerRaidLeadershipAA));
|
||||
Message_StringID(MT_Leadership, GAIN_RAID_LEADERSHIP_EXP);
|
||||
}
|
||||
else
|
||||
Message_StringID(MT_Leadership, MAX_RAID_LEADERSHIP_POINTS);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} //end !resexp
|
||||
|
||||
float aatotalmod = 1.0;
|
||||
if(zone->newzone_data.zone_exp_multiplier >= 0){
|
||||
aatotalmod *= zone->newzone_data.zone_exp_multiplier;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(RuleB(Character,UseRaceClassExpBonuses))
|
||||
{
|
||||
if(GetBaseRace() == HALFLING){
|
||||
aatotalmod *= 1.05;
|
||||
}
|
||||
|
||||
if(GetClass() == ROGUE || GetClass() == WARRIOR){
|
||||
aatotalmod *= 1.05;
|
||||
}
|
||||
}
|
||||
|
||||
if(RuleB(Zone, LevelBasedEXPMods)){
|
||||
if(zone->level_exp_mod[GetLevel()].ExpMod){
|
||||
add_exp *= zone->level_exp_mod[GetLevel()].ExpMod;
|
||||
add_aaxp *= zone->level_exp_mod[GetLevel()].AAExpMod;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 exp = GetEXP() + add_exp;
|
||||
|
||||
uint32 aaexp = (uint32)(RuleR(Character, AAExpMultiplier) * add_aaxp * aatotalmod);
|
||||
uint32 had_aaexp = GetAAXP();
|
||||
aaexp += had_aaexp;
|
||||
if(aaexp < had_aaexp)
|
||||
aaexp = had_aaexp; //watch for wrap
|
||||
|
||||
SetEXP(exp, aaexp, resexp);
|
||||
}
|
||||
|
||||
void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
|
||||
_log(CLIENT__EXP, "Attempting to Set Exp for %s (XP: %u, AAXP: %u, Rez: %s)", this->GetCleanName(), set_exp, set_aaxp, isrezzexp ? "true" : "false");
|
||||
//max_AAXP = GetEXPForLevel(52) - GetEXPForLevel(51); //GetEXPForLevel() doesn't depend on class/race, just level, so it shouldn't change between Clients
|
||||
max_AAXP = RuleI(AA, ExpPerPoint); //this may be redundant since we're doing this in Client::FinishConnState2()
|
||||
if (max_AAXP == 0 || GetEXPForLevel(GetLevel()) == 0xFFFFFFFF) {
|
||||
Message(13, "Error in Client::SetEXP. EXP not set.");
|
||||
return; // Must be invalid class/race
|
||||
}
|
||||
|
||||
|
||||
if ((set_exp + set_aaxp) > (m_pp.exp+m_pp.expAA)) {
|
||||
if (isrezzexp)
|
||||
this->Message_StringID(MT_Experience, REZ_REGAIN);
|
||||
else{
|
||||
if(this->IsGrouped())
|
||||
this->Message_StringID(MT_Experience, GAIN_GROUPXP);
|
||||
else if(IsRaidGrouped())
|
||||
Message_StringID(MT_Experience, GAIN_RAIDEXP);
|
||||
else
|
||||
this->Message_StringID(MT_Experience, GAIN_XP);
|
||||
}
|
||||
}
|
||||
else if((set_exp + set_aaxp) < (m_pp.exp+m_pp.expAA)){ //only loss message if you lose exp, no message if you gained/lost nothing.
|
||||
Message(15, "You have lost experience.");
|
||||
}
|
||||
|
||||
//check_level represents the level we should be when we have
|
||||
//this ammount of exp (once these loops complete)
|
||||
uint16 check_level = GetLevel()+1;
|
||||
//see if we gained any levels
|
||||
while (set_exp >= GetEXPForLevel(check_level)) {
|
||||
check_level++;
|
||||
if (check_level > 127) { //hard level cap
|
||||
check_level = 127;
|
||||
break;
|
||||
}
|
||||
if(GetMercID())
|
||||
UpdateMercLevel();
|
||||
}
|
||||
//see if we lost any levels
|
||||
while (set_exp < GetEXPForLevel(check_level-1)) {
|
||||
check_level--;
|
||||
if (check_level < 2) { //hard level minimum
|
||||
check_level = 2;
|
||||
break;
|
||||
}
|
||||
if(GetMercID())
|
||||
UpdateMercLevel();
|
||||
}
|
||||
check_level--;
|
||||
|
||||
|
||||
//see if we gained any AAs
|
||||
if (set_aaxp >= max_AAXP) {
|
||||
/*
|
||||
Note: AA exp is stored differently than normal exp.
|
||||
Exp points are only stored in m_pp.expAA until you
|
||||
gain a full AA point, once you gain it, a point is
|
||||
added to m_pp.aapoints and the ammount needed to gain
|
||||
that point is subtracted from m_pp.expAA
|
||||
|
||||
then, once they spend an AA point, it is subtracted from
|
||||
m_pp.aapoints. In theory it then goes into m_pp.aapoints_spent,
|
||||
but im not sure if we have that in the right spot.
|
||||
*/
|
||||
//record how many points we have
|
||||
uint32 last_unspentAA = m_pp.aapoints;
|
||||
|
||||
//figure out how many AA points we get from the exp were setting
|
||||
m_pp.aapoints = set_aaxp / max_AAXP;
|
||||
_log(CLIENT__EXP, "Calculating additional AA Points from AAXP for %s: %u / %u = %.1f points", this->GetCleanName(), set_aaxp, max_AAXP, (float)set_aaxp / (float)max_AAXP);
|
||||
|
||||
//get remainder exp points, set in PP below
|
||||
set_aaxp = set_aaxp - (max_AAXP * m_pp.aapoints);
|
||||
|
||||
//add in how many points we had
|
||||
m_pp.aapoints += last_unspentAA;
|
||||
//set_aaxp = m_pp.expAA % max_AAXP;
|
||||
|
||||
//figure out how many points were actually gained
|
||||
/*uint32 gained = m_pp.aapoints - last_unspentAA;*/ //unused
|
||||
|
||||
//Message(15, "You have gained %d skill points!!", m_pp.aapoints - last_unspentAA);
|
||||
char val1[20]={0};
|
||||
Message_StringID(MT_Experience, GAIN_ABILITY_POINT,ConvertArray(m_pp.aapoints, val1),m_pp.aapoints == 1 ? "" : "(s)"); //You have gained an ability point! You now have %1 ability point%2.
|
||||
//Message(15, "You now have %d skill points available to spend.", m_pp.aapoints);
|
||||
}
|
||||
|
||||
uint8 maxlevel = RuleI(Character, MaxExpLevel) + 1;
|
||||
|
||||
if(maxlevel <= 1)
|
||||
maxlevel = RuleI(Character, MaxLevel) + 1;
|
||||
|
||||
if(check_level > maxlevel) {
|
||||
check_level = maxlevel;
|
||||
set_exp = GetEXPForLevel(maxlevel);
|
||||
}
|
||||
|
||||
if(RuleB(Character, PerCharacterQglobalMaxLevel)){
|
||||
uint32 MaxLevel = GetCharMaxLevelFromQGlobal();
|
||||
if(MaxLevel){
|
||||
if(GetLevel() >= MaxLevel){
|
||||
uint32 expneeded = GetEXPForLevel(MaxLevel);
|
||||
if(set_exp > expneeded)
|
||||
{
|
||||
set_exp = expneeded;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((GetLevel() != check_level) && !(check_level >= maxlevel)) {
|
||||
char val1[20]={0};
|
||||
if (GetLevel() == check_level-1){
|
||||
Message_StringID(MT_Experience, GAIN_LEVEL,ConvertArray(check_level,val1));
|
||||
SendLevelAppearance();
|
||||
//Message(15, "You have gained a level! Welcome to level %i!", check_level);
|
||||
}
|
||||
if (GetLevel() == check_level){
|
||||
Message_StringID(MT_Experience, LOSE_LEVEL,ConvertArray(check_level,val1));
|
||||
//Message(15, "You lost a level! You are now level %i!", check_level);
|
||||
}
|
||||
else
|
||||
Message(15, "Welcome to level %i!", check_level);
|
||||
SetLevel(check_level);
|
||||
}
|
||||
|
||||
//If were at max level then stop gaining experience if we make it to the cap
|
||||
if(GetLevel() == maxlevel - 1){
|
||||
uint32 expneeded = GetEXPForLevel(maxlevel);
|
||||
if(set_exp > expneeded)
|
||||
{
|
||||
set_exp = expneeded;
|
||||
}
|
||||
}
|
||||
|
||||
//set the client's EXP and AAEXP
|
||||
m_pp.exp = set_exp;
|
||||
m_pp.expAA = set_aaxp;
|
||||
|
||||
if (GetLevel() < 51) {
|
||||
m_epp.perAA = 0; // turn off aa exp if they drop below 51
|
||||
} else
|
||||
SendAAStats(); //otherwise, send them an AA update
|
||||
|
||||
//send the expdata in any case so the xp bar isnt stuck after leveling
|
||||
uint32 tmpxp1 = GetEXPForLevel(GetLevel()+1);
|
||||
uint32 tmpxp2 = GetEXPForLevel(GetLevel());
|
||||
// Quag: crash bug fix... Divide by zero when tmpxp1 and 2 equalled each other, most likely the error case from GetEXPForLevel() (invalid class, etc)
|
||||
if (tmpxp1 != tmpxp2 && tmpxp1 != 0xFFFFFFFF && tmpxp2 != 0xFFFFFFFF) {
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_ExpUpdate, sizeof(ExpUpdate_Struct));
|
||||
ExpUpdate_Struct* eu = (ExpUpdate_Struct*)outapp->pBuffer;
|
||||
float tmpxp = (float) ( (float) set_exp-tmpxp2 ) / ( (float) tmpxp1-tmpxp2 );
|
||||
eu->exp = (uint32)(330.0f * tmpxp);
|
||||
FastQueuePacket(&outapp);
|
||||
}
|
||||
|
||||
if (admin>=100 && GetGM()) {
|
||||
char val1[20]={0};
|
||||
char val2[20]={0};
|
||||
char val3[20]={0};
|
||||
Message_StringID(MT_Experience, GM_GAINXP,ConvertArray(set_aaxp,val1),ConvertArray(set_exp,val2),ConvertArray(GetEXPForLevel(GetLevel()+1),val3)); //[GM] You have gained %1 AXP and %2 EXP (%3).
|
||||
//Message(15, "[GM] You now have %d / %d EXP and %d / %d AA exp.", set_exp, GetEXPForLevel(GetLevel()+1), set_aaxp, max_AAXP);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::SetLevel(uint8 set_level, bool command)
|
||||
{
|
||||
if (GetEXPForLevel(set_level) == 0xFFFFFFFF) {
|
||||
LogFile->write(EQEMuLog::Error,"Client::SetLevel() GetEXPForLevel(%i) = 0xFFFFFFFF", set_level);
|
||||
return;
|
||||
}
|
||||
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_LevelUpdate, sizeof(LevelUpdate_Struct));
|
||||
LevelUpdate_Struct* lu = (LevelUpdate_Struct*)outapp->pBuffer;
|
||||
lu->level = set_level;
|
||||
if(m_pp.level2 != 0)
|
||||
lu->level_old = m_pp.level2;
|
||||
else
|
||||
lu->level_old = level;
|
||||
|
||||
level = set_level;
|
||||
|
||||
if(IsRaidGrouped())
|
||||
{
|
||||
Raid *r = this->GetRaid();
|
||||
if(r){
|
||||
r->UpdateLevel(GetName(), set_level);
|
||||
}
|
||||
}
|
||||
if(set_level > m_pp.level2)
|
||||
{
|
||||
if(m_pp.level2 == 0)
|
||||
m_pp.points += 5;
|
||||
else
|
||||
m_pp.points += (5 * (set_level - m_pp.level2));
|
||||
|
||||
m_pp.level2 = set_level;
|
||||
}
|
||||
if(set_level > m_pp.level) {
|
||||
parse->EventPlayer(EVENT_LEVEL_UP, this, "", 0);
|
||||
}
|
||||
|
||||
m_pp.level = set_level;
|
||||
if (command){
|
||||
m_pp.exp = GetEXPForLevel(set_level);
|
||||
Message(15, "Welcome to level %i!", set_level);
|
||||
lu->exp = 0;
|
||||
}
|
||||
else {
|
||||
float tmpxp = (float) ( (float) m_pp.exp - GetEXPForLevel( GetLevel() )) /
|
||||
( (float) GetEXPForLevel(GetLevel()+1) - GetEXPForLevel(GetLevel()));
|
||||
lu->exp = (uint32)(330.0f * tmpxp);
|
||||
}
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
this->SendAppearancePacket(AT_WhoLevel, set_level); // who level change
|
||||
|
||||
LogFile->write(EQEMuLog::Normal,"Setting Level for %s to %i", GetName(), set_level);
|
||||
|
||||
CalcBonuses();
|
||||
if(!RuleB(Character, HealOnLevel))
|
||||
{
|
||||
int mhp = CalcMaxHP();
|
||||
if(GetHP() > mhp)
|
||||
SetHP(mhp);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetHP(CalcMaxHP()); // Why not, lets give them a free heal
|
||||
}
|
||||
|
||||
DoTributeUpdate();
|
||||
SendHPUpdate();
|
||||
SetMana(CalcMaxMana());
|
||||
UpdateWho();
|
||||
if(GetMerc())
|
||||
UpdateMercLevel();
|
||||
Save();
|
||||
}
|
||||
|
||||
// Note: The client calculates exp separately, we cant change this function
|
||||
// Add: You can set the values you want now, client will be always sync :) - Merkur
|
||||
uint32 Client::GetEXPForLevel(uint16 check_level)
|
||||
{
|
||||
|
||||
uint16 check_levelm1 = check_level-1;
|
||||
float mod;
|
||||
if (check_level < 31)
|
||||
mod = 1.0;
|
||||
else if (check_level < 36)
|
||||
mod = 1.1;
|
||||
else if (check_level < 41)
|
||||
mod = 1.2;
|
||||
else if (check_level < 46)
|
||||
mod = 1.3;
|
||||
else if (check_level < 52)
|
||||
mod = 1.4;
|
||||
else if (check_level < 53)
|
||||
mod = 1.5;
|
||||
else if (check_level < 54)
|
||||
mod = 1.6;
|
||||
else if (check_level < 55)
|
||||
mod = 1.7;
|
||||
else if (check_level < 56)
|
||||
mod = 1.9;
|
||||
else if (check_level < 57)
|
||||
mod = 2.1;
|
||||
else if (check_level < 58)
|
||||
mod = 2.3;
|
||||
else if (check_level < 59)
|
||||
mod = 2.5;
|
||||
else if (check_level < 60)
|
||||
mod = 2.7;
|
||||
else if (check_level < 61)
|
||||
mod = 3.0;
|
||||
else
|
||||
mod = 3.1;
|
||||
|
||||
float base = (check_levelm1)*(check_levelm1)*(check_levelm1);
|
||||
|
||||
mod *= 1000;
|
||||
|
||||
return(uint32(base * mod));
|
||||
}
|
||||
|
||||
void Client::AddLevelBasedExp(uint8 exp_percentage, uint8 max_level) {
|
||||
|
||||
if (exp_percentage > 100)
|
||||
{
|
||||
exp_percentage = 100;
|
||||
}
|
||||
|
||||
if (!max_level || GetLevel() < max_level)
|
||||
{
|
||||
max_level = GetLevel();
|
||||
}
|
||||
|
||||
uint32 newexp = GetEXP() + ((GetEXPForLevel(max_level + 1) - GetEXPForLevel(max_level)) * exp_percentage / 100);
|
||||
|
||||
SetEXP(newexp, GetAAXP());
|
||||
}
|
||||
|
||||
void Group::SplitExp(uint32 exp, Mob* other) {
|
||||
if( other->CastToNPC()->MerchantType != 0 ) // Ensure NPC isn't a merchant
|
||||
return;
|
||||
|
||||
if(other->GetOwner() && other->GetOwner()->IsClient()) // Ensure owner isn't pc
|
||||
return;
|
||||
|
||||
unsigned int i;
|
||||
uint32 groupexp = exp;
|
||||
uint8 membercount = 0;
|
||||
uint8 maxlevel = 1;
|
||||
|
||||
for (i = 0; i < MAX_GROUP_MEMBERS; i++) {
|
||||
if (members[i] != NULL) {
|
||||
if(members[i]->GetLevel() > maxlevel)
|
||||
maxlevel = members[i]->GetLevel();
|
||||
|
||||
membercount++;
|
||||
}
|
||||
}
|
||||
|
||||
float groupmod;
|
||||
if (membercount == 2)
|
||||
groupmod = 1.2;
|
||||
else if (membercount == 3)
|
||||
groupmod = 1.4;
|
||||
else if (membercount == 4)
|
||||
groupmod = 1.6;
|
||||
else if (membercount == 5)
|
||||
groupmod = 1.8;
|
||||
else if (membercount == 6)
|
||||
groupmod = 2.16;
|
||||
else
|
||||
groupmod = 1.0;
|
||||
|
||||
groupexp += (uint32)((float)exp * groupmod * (RuleR(Character, GroupExpMultiplier)));
|
||||
|
||||
int conlevel = Mob::GetLevelCon(maxlevel, other->GetLevel());
|
||||
if(conlevel == CON_GREEN)
|
||||
return; //no exp for greenies...
|
||||
|
||||
if (membercount == 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < MAX_GROUP_MEMBERS; i++) {
|
||||
if (members[i] != NULL && members[i]->IsClient()) // If Group Member is Client
|
||||
{
|
||||
Client *cmember = members[i]->CastToClient();
|
||||
// add exp + exp cap
|
||||
int16 diff = cmember->GetLevel() - maxlevel;
|
||||
int16 maxdiff = -(cmember->GetLevel()*15/10 - cmember->GetLevel());
|
||||
if(maxdiff > -5)
|
||||
maxdiff = -5;
|
||||
if (diff >= (maxdiff)) { /*Instead of person who killed the mob, the person who has the highest level in the group*/
|
||||
uint32 tmp = (cmember->GetLevel()+3) * (cmember->GetLevel()+3) * 75 * 35 / 10;
|
||||
uint32 tmp2 = groupexp / membercount;
|
||||
cmember->AddEXP( tmp < tmp2 ? tmp : tmp2, conlevel );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Raid::SplitExp(uint32 exp, Mob* other) {
|
||||
if( other->CastToNPC()->MerchantType != 0 ) // Ensure NPC isn't a merchant
|
||||
return;
|
||||
|
||||
if(other->GetOwner() && other->GetOwner()->IsClient()) // Ensure owner isn't pc
|
||||
return;
|
||||
|
||||
uint32 groupexp = exp;
|
||||
uint8 membercount = 0;
|
||||
uint8 maxlevel = 1;
|
||||
|
||||
for (int i = 0; i < MAX_RAID_MEMBERS; i++) {
|
||||
if (members[i].member != NULL) {
|
||||
if(members[i].member->GetLevel() > maxlevel)
|
||||
maxlevel = members[i].member->GetLevel();
|
||||
|
||||
membercount++;
|
||||
}
|
||||
}
|
||||
|
||||
groupexp = (uint32)((float)groupexp * (1.0f-(RuleR(Character, RaidExpMultiplier))));
|
||||
|
||||
int conlevel = Mob::GetLevelCon(maxlevel, other->GetLevel());
|
||||
if(conlevel == CON_GREEN)
|
||||
return; //no exp for greenies...
|
||||
|
||||
if (membercount == 0)
|
||||
return;
|
||||
|
||||
for (unsigned int x = 0; x < MAX_RAID_MEMBERS; x++) {
|
||||
if (members[x].member != NULL) // If Group Member is Client
|
||||
{
|
||||
Client *cmember = members[x].member;
|
||||
// add exp + exp cap
|
||||
int16 diff = cmember->GetLevel() - maxlevel;
|
||||
int16 maxdiff = -(cmember->GetLevel()*15/10 - cmember->GetLevel());
|
||||
if(maxdiff > -5)
|
||||
maxdiff = -5;
|
||||
if (diff >= (maxdiff)) { /*Instead of person who killed the mob, the person who has the highest level in the group*/
|
||||
uint32 tmp = (cmember->GetLevel()+3) * (cmember->GetLevel()+3) * 75 * 35 / 10;
|
||||
uint32 tmp2 = (groupexp / membercount) + 1;
|
||||
cmember->AddEXP( tmp < tmp2 ? tmp : tmp2, conlevel );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Client::SetLeadershipEXP(uint32 group_exp, uint32 raid_exp) {
|
||||
while(group_exp >= GROUP_EXP_PER_POINT) {
|
||||
group_exp -= GROUP_EXP_PER_POINT;
|
||||
m_pp.group_leadership_points++;
|
||||
Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_POINT);
|
||||
}
|
||||
while(raid_exp >= RAID_EXP_PER_POINT) {
|
||||
raid_exp -= RAID_EXP_PER_POINT;
|
||||
m_pp.raid_leadership_points++;
|
||||
Message_StringID(MT_Leadership, GAIN_RAID_LEADERSHIP_POINT);
|
||||
}
|
||||
|
||||
m_pp.group_leadership_exp = group_exp;
|
||||
m_pp.raid_leadership_exp = raid_exp;
|
||||
|
||||
SendLeadershipEXPUpdate();
|
||||
}
|
||||
|
||||
void Client::AddLeadershipEXP(uint32 group_exp, uint32 raid_exp) {
|
||||
SetLeadershipEXP(GetGroupEXP() + group_exp, GetRaidEXP() + raid_exp);
|
||||
}
|
||||
|
||||
void Client::SendLeadershipEXPUpdate() {
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_LeadershipExpUpdate, sizeof(LeadershipExpUpdate_Struct));
|
||||
LeadershipExpUpdate_Struct* eu = (LeadershipExpUpdate_Struct *) outapp->pBuffer;
|
||||
|
||||
eu->group_leadership_exp = m_pp.group_leadership_exp;
|
||||
eu->group_leadership_points = m_pp.group_leadership_points;
|
||||
eu->raid_leadership_exp = m_pp.raid_leadership_exp;
|
||||
eu->raid_leadership_points = m_pp.raid_leadership_points;
|
||||
|
||||
FastQueuePacket(&outapp);
|
||||
}
|
||||
|
||||
uint32 Client::GetCharMaxLevelFromQGlobal() {
|
||||
|
||||
QGlobalCache *char_c = NULL;
|
||||
char_c = this->GetQGlobals();
|
||||
|
||||
std::list<QGlobal> globalMap;
|
||||
uint32 ntype = 0;
|
||||
|
||||
if(char_c)
|
||||
{
|
||||
QGlobalCache::Combine(globalMap, char_c->GetBucket(), ntype, this->CharacterID(), zone->GetZoneID());
|
||||
}
|
||||
|
||||
std::list<QGlobal>::iterator iter = globalMap.begin();
|
||||
uint32 gcount = 0;
|
||||
while(iter != globalMap.end())
|
||||
{
|
||||
if((*iter).name.compare("CharMaxLevel") == 0){
|
||||
return atoi((*iter).value.c_str());
|
||||
}
|
||||
++iter;
|
||||
++gcount;
|
||||
}
|
||||
|
||||
return false; // Default is false
|
||||
}
|
||||
+1064
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,77 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef FACTION_H
|
||||
#define FACTION_H
|
||||
|
||||
#include "../common/types.h"
|
||||
#include "features.h"
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
enum FACTION_VALUE {
|
||||
FACTION_ALLY = 1,
|
||||
FACTION_WARMLY = 2,
|
||||
FACTION_KINDLY = 3,
|
||||
FACTION_AMIABLE = 4,
|
||||
|
||||
FACTION_INDIFFERENT = 5,
|
||||
|
||||
FACTION_APPREHENSIVE = 6,
|
||||
FACTION_DUBIOUS = 7,
|
||||
FACTION_THREATENLY = 8,
|
||||
FACTION_SCOWLS = 9
|
||||
};
|
||||
|
||||
struct NPCFactionList {
|
||||
uint32 id;
|
||||
uint32 primaryfaction;
|
||||
bool assistprimaryfaction;
|
||||
uint32 factionid[MAX_NPC_FACTIONS];
|
||||
int32 factionvalue[MAX_NPC_FACTIONS];
|
||||
int8 factionnpcvalue[MAX_NPC_FACTIONS];
|
||||
uint8 factiontemp[MAX_NPC_FACTIONS];
|
||||
};
|
||||
|
||||
struct FactionMods
|
||||
{
|
||||
int32 base;
|
||||
int32 class_mod;
|
||||
int32 race_mod;
|
||||
int32 deity_mod;
|
||||
};
|
||||
struct Faction {
|
||||
int32 id;
|
||||
std::map<std::string, int16> mods;
|
||||
int16 base;
|
||||
char name[50];
|
||||
};
|
||||
typedef map<uint32, int16> faction_map;
|
||||
|
||||
struct NPCFaction
|
||||
{
|
||||
uint32 factionID;
|
||||
int32 value_mod;
|
||||
int8 npc_value;
|
||||
uint8 temp;
|
||||
//bool primary;
|
||||
};
|
||||
|
||||
const char *FactionValueToString(FACTION_VALUE fv);
|
||||
char* BuildFactionMessage(int32 tmpvalue, int32 faction_id, int32 totalvalue, uint8 temp);
|
||||
FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value);
|
||||
#endif
|
||||
@@ -0,0 +1,645 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "../common/debug.h"
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "../common/rulesys.h"
|
||||
#include "../common/MiscFunctions.h"
|
||||
#include "zone_profile.h"
|
||||
#include "map.h"
|
||||
#include "zone.h"
|
||||
#include "pathing.h"
|
||||
#ifdef _WINDOWS
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
|
||||
extern Zone* zone;
|
||||
|
||||
#define FEAR_PATHING_DEBUG
|
||||
|
||||
|
||||
//this is called whenever we are damaged to process possible fleeing
|
||||
void Mob::CheckFlee() {
|
||||
//if were allready fleeing, dont need to check more...
|
||||
if(flee_mode && curfp)
|
||||
return;
|
||||
|
||||
//dont bother if we are immune to fleeing
|
||||
if(SpecAttacks[IMMUNE_FLEEING] || spellbonuses.ImmuneToFlee)
|
||||
return;
|
||||
|
||||
if(!flee_timer.Check())
|
||||
return; //only do all this stuff every little while, since
|
||||
//its not essential that we start running RIGHT away
|
||||
|
||||
//see if were possibly hurt enough
|
||||
float ratio = GetHPRatio();
|
||||
if(ratio >= RuleI(Combat, FleeHPRatio))
|
||||
return;
|
||||
|
||||
//we might be hurt enough, check con now..
|
||||
Mob *hate_top = GetHateTop();
|
||||
if(!hate_top) {
|
||||
//this should never happen...
|
||||
StartFleeing();
|
||||
return;
|
||||
}
|
||||
|
||||
float other_ratio = hate_top->GetHPRatio();
|
||||
if(other_ratio < 20) {
|
||||
//our hate top is almost dead too... stay and fight
|
||||
return;
|
||||
}
|
||||
|
||||
//base our flee ratio on our con. this is how the
|
||||
//attacker sees the mob, since this is all we can observe
|
||||
uint32 con = GetLevelCon(hate_top->GetLevel(), GetLevel());
|
||||
float run_ratio;
|
||||
switch(con) {
|
||||
//these values are not 100% researched
|
||||
case CON_GREEN:
|
||||
run_ratio = RuleI(Combat, FleeHPRatio);
|
||||
break;
|
||||
case CON_LIGHTBLUE:
|
||||
run_ratio = RuleI(Combat, FleeHPRatio) * 8 / 10;
|
||||
break;
|
||||
case CON_BLUE:
|
||||
run_ratio = RuleI(Combat, FleeHPRatio) * 6 / 10;
|
||||
break;
|
||||
default:
|
||||
run_ratio = RuleI(Combat, FleeHPRatio) * 4 / 10;
|
||||
break;
|
||||
}
|
||||
if(ratio < run_ratio)
|
||||
{
|
||||
if( RuleB(Combat, FleeIfNotAlone)
|
||||
|| ( !RuleB(Combat, FleeIfNotAlone)
|
||||
&& (entity_list.GetHatedCount(hate_top, this) == 0)))
|
||||
StartFleeing();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Mob::ProcessFlee() {
|
||||
|
||||
//Stop fleeing if effect is applied after they start to run.
|
||||
//When ImmuneToFlee effect fades it will turn fear back on and check if it can still flee.
|
||||
if(flee_mode && (SpecAttacks[IMMUNE_FLEEING] || spellbonuses.ImmuneToFlee) && !spellbonuses.IsFeared){
|
||||
curfp = false;
|
||||
return;
|
||||
}
|
||||
|
||||
//see if we are still dying, if so, do nothing
|
||||
if(GetHPRatio() < (float)RuleI(Combat, FleeHPRatio))
|
||||
return;
|
||||
|
||||
//we are not dying anymore... see what we do next
|
||||
|
||||
flee_mode = false;
|
||||
|
||||
//see if we are legitimately feared now
|
||||
if(!spellbonuses.IsFeared) {
|
||||
//not feared... were done...
|
||||
curfp = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
float Mob::GetFearSpeed() {
|
||||
if(flee_mode) {
|
||||
//we know ratio < FLEE_HP_RATIO
|
||||
float speed = GetRunspeed();
|
||||
float ratio = GetHPRatio();
|
||||
|
||||
// mob's movement will halt with a decent snare at HP specified by rule.
|
||||
if (ratio <= RuleI(Combat, FleeSnareHPRatio) && GetSnaredAmount() > 40) {
|
||||
return 0.0001f;
|
||||
}
|
||||
|
||||
if (ratio < FLEE_HP_MINSPEED)
|
||||
ratio = FLEE_HP_MINSPEED;
|
||||
|
||||
speed = speed * 0.5 * ratio / 100;
|
||||
|
||||
return(speed);
|
||||
}
|
||||
return(GetRunspeed());
|
||||
}
|
||||
|
||||
void Mob::CalculateNewFearpoint()
|
||||
{
|
||||
if(RuleB(Pathing, Fear) && zone->pathing)
|
||||
{
|
||||
int Node = zone->pathing->GetRandomPathNode();
|
||||
|
||||
VERTEX Loc = zone->pathing->GetPathNodeCoordinates(Node);
|
||||
|
||||
++Loc.z;
|
||||
|
||||
VERTEX CurrentPosition(GetX(), GetY(), GetZ());
|
||||
|
||||
list<int> Route = zone->pathing->FindRoute(CurrentPosition, Loc);
|
||||
|
||||
if(Route.size() > 0)
|
||||
{
|
||||
fear_walkto_x = Loc.x;
|
||||
fear_walkto_y = Loc.y;
|
||||
fear_walkto_z = Loc.z;
|
||||
curfp = true;
|
||||
|
||||
mlog(PATHING__DEBUG, "Feared to node %i (%8.3f, %8.3f, %8.3f)", Node, Loc.x, Loc.y, Loc.z);
|
||||
return;
|
||||
}
|
||||
|
||||
mlog(PATHING__DEBUG, "No path found to selected node. Falling through to old fear point selection.");
|
||||
}
|
||||
|
||||
int loop = 0;
|
||||
float ranx, rany, ranz;
|
||||
curfp = false;
|
||||
while (loop < 100) //Max 100 tries
|
||||
{
|
||||
int ran = 250 - (loop*2);
|
||||
loop++;
|
||||
ranx = GetX()+MakeRandomInt(0, ran-1)-MakeRandomInt(0, ran-1);
|
||||
rany = GetY()+MakeRandomInt(0, ran-1)-MakeRandomInt(0, ran-1);
|
||||
ranz = FindGroundZ(ranx,rany);
|
||||
if (ranz == -999999)
|
||||
continue;
|
||||
float fdist = ranz - GetZ();
|
||||
if (fdist >= -12 && fdist <= 12 && CheckCoordLosNoZLeaps(GetX(),GetY(),GetZ(),ranx,rany,ranz))
|
||||
{
|
||||
curfp = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (curfp)
|
||||
{
|
||||
fear_walkto_x = ranx;
|
||||
fear_walkto_y = rany;
|
||||
fear_walkto_z = ranz;
|
||||
}
|
||||
else //Break fear
|
||||
{
|
||||
BuffFadeByEffect(SE_Fear);
|
||||
}
|
||||
}
|
||||
|
||||
//we need to start acting scared...
|
||||
//old fear function, kept for ref.
|
||||
/*void Mob::SetFeared(Mob *caster, uint32 duration, bool flee) {
|
||||
//special args to stop fear
|
||||
if(caster == NULL && duration == 0) {
|
||||
fear_state = fearStateNotFeared;
|
||||
#ifdef FLEE_HP_RATIO
|
||||
flee_mode = false;
|
||||
#endif
|
||||
safe_delete(fear_path_state);
|
||||
return;
|
||||
}
|
||||
|
||||
flee_mode = flee;
|
||||
|
||||
//fear dosent work without at least maps
|
||||
if(zone->zonemap == NULL) {
|
||||
fear_state = fearStateStuck;
|
||||
return; //just stand there
|
||||
}
|
||||
|
||||
//if we are allready feared, and we are on a fear grid..
|
||||
//then just stay happy on the grid...
|
||||
if(fear_path_state != NULL) {
|
||||
if(fear_state != fearStateGrid) {
|
||||
LogFile->write(EQEMuLog::Debug, "Umm... %s has a fear path state, but is not in a grid state. Wtf?", GetName());
|
||||
fear_state = fearStateGrid;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//try to run straight away from the caster
|
||||
VERTEX hit, fear_vector;
|
||||
if(FearTryStraight(caster, duration, flee, hit, fear_vector)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//OK, so if we just run, we are going to hit something...
|
||||
//now we have to think a little more.
|
||||
|
||||
//first, try to find a fear node that we can see.
|
||||
if(zone->pathing != NULL) {
|
||||
fear_path_state = new MobFearState();
|
||||
if(zone->pathing->FindNearestFear(fear_path_state, GetX(), GetY(), GetZ())) {
|
||||
#ifdef FEAR_PATHING_DEBUG
|
||||
LogFile->write(EQEMuLog::Debug, "Fear Pathing Start: found path, moving from (%.2f, %.2f, %.2f) to path node (%.2f, %.2f, %.2f)",
|
||||
GetX(), GetY(), GetZ(), fear_path_state->x, fear_path_state->y, fear_path_state->z);
|
||||
#endif
|
||||
//we found a fear node... were on our way..
|
||||
cur_wp_x = fear_path_state->x;
|
||||
cur_wp_y = fear_path_state->y;
|
||||
cur_wp_z = fear_path_state->z;
|
||||
fear_state = fearStateGrid;
|
||||
return;
|
||||
}
|
||||
|
||||
//we have failed to find a path, so we dont need this..
|
||||
safe_delete(fear_path_state);
|
||||
}
|
||||
|
||||
//if we cannot just run, and we cannot see any paths, then
|
||||
//we will give one last ditch effort to find a legit path. We
|
||||
//will run as far as we can away from the player, and hope we
|
||||
//can see a path from there if not, we will start breaking rules
|
||||
|
||||
#ifdef FEAR_PATHING_DEBUG
|
||||
LogFile->write(EQEMuLog::Debug, "Fear Pathing Start: Hope run from (%.2f, %.2f, %.2f), hit at (%.2f, %.2f, %.2f)",
|
||||
GetX(), GetY(), GetZ(), hit.x, hit.y, hit.z);
|
||||
#endif
|
||||
//use the hit point - a little + a little Z as the first waypoint.
|
||||
cur_wp_x = hit.x - fear_vector.x * 2;
|
||||
cur_wp_y = hit.y - fear_vector.y * 2;
|
||||
cur_wp_z = GetZ();
|
||||
fear_state = fearStateRunning;
|
||||
}
|
||||
//old fear function, kept for ref.
|
||||
bool Mob::FearTryStraight(Mob *caster, uint32 duration, bool flee, VERTEX &hit, VERTEX &fear_vector) {
|
||||
//gotta have somebody to run from
|
||||
if(caster == NULL)
|
||||
return(false);
|
||||
|
||||
//our goal is to run along this vector...
|
||||
fear_vector.x = GetX() - caster->GetX();
|
||||
fear_vector.y = GetY() - caster->GetY();
|
||||
fear_vector.z = 0; //I dont see any reason to use Z
|
||||
float mag = sqrtf(fear_vector.x*fear_vector.x + fear_vector.y*fear_vector.y);
|
||||
fear_vector.x /= mag;
|
||||
fear_vector.y /= mag;
|
||||
|
||||
//now see if we can just run without hitting anything...
|
||||
VERTEX start, end;
|
||||
start.x = GetX();
|
||||
start.y = GetY();
|
||||
start.z = GetZ() + 5.0; //raise up a little over small bumps
|
||||
|
||||
//distance moved per movement tic.
|
||||
float distance = NPC_SPEED_MULTIPLIER * GetFearSpeed();
|
||||
//times number of movement tics in the spell.
|
||||
distance *= float(duration) / float(AImovement_duration);
|
||||
|
||||
end.x = start.x + fear_vector.x * distance;
|
||||
end.y = start.y + fear_vector.y * distance;
|
||||
end.z = start.z;
|
||||
|
||||
if(!zone->zonemap->LineIntersectsZone(start, end, 0.5, &hit, NULL)) {
|
||||
#ifdef FEAR_PATHING_DEBUG
|
||||
LogFile->write(EQEMuLog::Debug, "Fear Pathing Start: can run entire vector from (%.2f, %.2f, %.2f) to (%.2f, %.2f, %.2f)",
|
||||
GetX(), GetY(), GetZ(), end.x, end.y, end.z);
|
||||
#endif
|
||||
//no hit, we can run this whole vector.
|
||||
cur_wp_x = end.x;
|
||||
cur_wp_y = end.y;
|
||||
cur_wp_z = GetZ();
|
||||
fear_state = fearStateRunningForever;
|
||||
return(true); //were done, nothing difficult needed.
|
||||
}
|
||||
|
||||
return(false);
|
||||
}
|
||||
|
||||
//old fear function, kept for ref.
|
||||
void Mob::CalculateFearPosition() {
|
||||
if(zone->zonemap == NULL || fear_state == fearStateStuck) {
|
||||
return; //just stand there
|
||||
}
|
||||
|
||||
//This is the entire movement section, right here:
|
||||
if (cur_wp_x != GetX() && cur_wp_y != GetY()) {
|
||||
// not at waypoint yet, so keep moving
|
||||
CalculateNewPosition2(cur_wp_x, cur_wp_y, cur_wp_z, GetFearSpeed(), true);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//we have reached our waypoint, now what?
|
||||
//figure out a new waypoint to run at...
|
||||
|
||||
if(fear_state == fearStateRunningForever) {
|
||||
if(flee_mode) {
|
||||
//a fleeing mob may run away again
|
||||
VERTEX hit, fear_vector;
|
||||
if(FearTryStraight(GetHateTop(), FLEE_RUN_DURATION, true, hit, fear_vector))
|
||||
return; //we are running again
|
||||
//else, we need to find a grid, so act like we were on a hope run
|
||||
fear_state = fearStateRunning;
|
||||
}
|
||||
#ifndef FORCE_FEAR_TO_RUN
|
||||
else {
|
||||
//we were supposed to run forever, but we did not...
|
||||
//should re-fear ourself or something??
|
||||
fear_state = fearStateStuck;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//first see if we are on a path. if so our life is easy
|
||||
if(fear_state == fearStateGrid && fear_path_state) {
|
||||
//assume that we have zone->pathing since we got to this state.
|
||||
if(!zone->pathing->NextFearPath(fear_path_state)) {
|
||||
//this is bad, we were on a path and now its giving us
|
||||
//an error... we dont have a good way to deal with this
|
||||
fear_state = fearStateStuck;
|
||||
return;
|
||||
}
|
||||
#ifdef FEAR_PATHING_DEBUG
|
||||
LogFile->write(EQEMuLog::Debug, "Fear Pathing: on path, moving from (%.2f, %.2f, %.2f) to path node (%.2f, %.2f, %.2f)",
|
||||
GetX(), GetY(), GetZ(), fear_path_state->x, fear_path_state->y, fear_path_state->z);
|
||||
#endif
|
||||
//we found a fear node... were on our way..
|
||||
cur_wp_x = fear_path_state->x;
|
||||
cur_wp_y = fear_path_state->y;
|
||||
cur_wp_z = fear_path_state->z;
|
||||
|
||||
CalculateNewPosition2(cur_wp_x, cur_wp_y, cur_wp_z, GetFearSpeed(), true);
|
||||
return;
|
||||
}
|
||||
|
||||
//the only valid state left is fearStateRunning, where we try to
|
||||
//find a grid once we reach our waypoint, which we have..
|
||||
if(fear_state != fearStateRunning) {
|
||||
//wtf... unknown state
|
||||
LogFile->write(EQEMuLog::Debug, "Fear Pathing: Reached our fear waypoint, but we are in an unknown state %d... stopping.", fear_state);
|
||||
fear_state = fearStateStuck;
|
||||
return;
|
||||
}
|
||||
|
||||
//we wanted to try to find a waypoint now, so lets try..
|
||||
if(zone->pathing != NULL) {
|
||||
fear_path_state = new MobFearState();
|
||||
|
||||
if(zone->pathing->FindNearestFear(fear_path_state, GetX(), GetY(), GetZ())) {
|
||||
#ifdef FEAR_PATHING_DEBUG
|
||||
LogFile->write(EQEMuLog::Debug, "Fear Pathing: ran to find path, moving from (%.2f, %.2f, %.2f) to path node (%.2f, %.2f, %.2f)",
|
||||
GetX(), GetY(), GetZ(), fear_path_state->x, fear_path_state->y, fear_path_state->z);
|
||||
#endif
|
||||
//we found a fear node... were on our way..
|
||||
cur_wp_x = fear_path_state->x;
|
||||
cur_wp_y = fear_path_state->y;
|
||||
cur_wp_z = fear_path_state->z;
|
||||
fear_state = fearStateGrid;
|
||||
CalculateNewPosition2(cur_wp_x, cur_wp_y, cur_wp_z, GetFearSpeed(), true);
|
||||
return;
|
||||
}
|
||||
|
||||
//if we get here... all valid methods have failed
|
||||
|
||||
#ifdef FORCE_FEAR_TO_RUN
|
||||
//ok, now we start making shit up
|
||||
|
||||
//for now, we will limit our bullshitting to ignoring LOS
|
||||
//when finding a pathing node, we SHOULD always get something..
|
||||
//do not force a path if we are fleeing
|
||||
if(!flee_mode && zone->pathing->FindNearestFear(fear_path_state, GetX(), GetY(), GetZ(), false)) {
|
||||
#ifdef FEAR_PATHING_DEBUG
|
||||
LogFile->write(EQEMuLog::Debug, "Fear Pathing: Bullshit Path from (%.2f, %.2f, %.2f) to path node (%.2f, %.2f, %.2f)",
|
||||
GetX(), GetY(), GetZ(), fear_path_state->x, fear_path_state->y, fear_path_state->z);
|
||||
#endif
|
||||
//we found a fear node... were on our way..
|
||||
cur_wp_x = fear_path_state->x;
|
||||
cur_wp_y = fear_path_state->y;
|
||||
cur_wp_z = fear_path_state->z;
|
||||
fear_state = fearStateGrid;
|
||||
CalculateNewPosition2(cur_wp_x, cur_wp_y, cur_wp_z, GetFearSpeed(), true);
|
||||
return;
|
||||
}
|
||||
#endif //FORCE_FEAR_TO_RUN
|
||||
|
||||
//we have failed to find a path once again, so we dont need this..
|
||||
safe_delete(fear_path_state);
|
||||
}
|
||||
|
||||
//if we get HERE... then NOTHING worked... just stick
|
||||
fear_state = fearStateStuck;
|
||||
|
||||
//end of function, everything else is #ifdef'd out
|
||||
//}
|
||||
|
||||
//I dont wanna get rid of this right now because it was a lot of hard
|
||||
//work to write... but it dosent work reliably, so oh well..
|
||||
#ifdef OLD_FEAR_PATHING
|
||||
/*
|
||||
The idea...
|
||||
|
||||
try to run along fear vector.
|
||||
If we can see along it, run
|
||||
otherwise, try to walk up a hill along the same vector
|
||||
then try to move along a wall along largest component of FV
|
||||
if cant move, change stae to stuck.
|
||||
|
||||
once we know a place to run, use the waypoint code to do it
|
||||
then if combat ends, we will reach the waypoint and
|
||||
|
||||
|
||||
*/
|
||||
/*
|
||||
//first try our original fear vector again...
|
||||
VERTEX start, end, hit, normalhit;
|
||||
start.x = GetX() - fear_vector.x * 0.4;
|
||||
start.y = GetY() - fear_vector.y * 0.4;
|
||||
start.z = GetZ() + 6.0; //raise up a little over small bumps
|
||||
|
||||
end.x = start.x + fear_vector.x * 10;
|
||||
end.y = start.y + fear_vector.y * 10;
|
||||
end.z = start.z;
|
||||
|
||||
if(!zone->zonemap->LineIntersectsZone(start, end, 0.5, &normalhit, NULL)) {
|
||||
#ifdef FEAR_PATHING_DEBUG
|
||||
LogFile->write(EQEMuLog::Debug, "Fear Pathing: From (%.2f, %.2f, %.2f) normal run to (%.2f, %.2f, %.2f)",
|
||||
GetX(), GetY(), GetZ(), end.x, end.y, end.z);
|
||||
#endif
|
||||
//we can run along this vector without hitting anything...
|
||||
cur_wp_x = end.x;
|
||||
cur_wp_y = end.y;
|
||||
cur_wp_z = end.z - 6.0;
|
||||
CalculateNewPosition2(cur_wp_x, cur_wp_y, cur_wp_z, GetRunspeed(), true);
|
||||
return;
|
||||
}
|
||||
//see if we can make ANY useful progress along that vector
|
||||
|
||||
//first, adjust normalhit to back up a little bit
|
||||
//so we dont run through the wall
|
||||
normalhit.x -= 0.4 * fear_vector.x;
|
||||
normalhit.y -= 0.4 * fear_vector.y;
|
||||
|
||||
float xd = normalhit.x - start.x;
|
||||
if(xd < 0)
|
||||
xd = 0 - xd;
|
||||
float yd = normalhit.y - start.y;
|
||||
if(yd < 0)
|
||||
yd = 0 - yd;
|
||||
|
||||
//this 2 is arbitrary
|
||||
if((xd+yd) > 2.0) {
|
||||
#ifdef FEAR_PATHING_DEBUG
|
||||
LogFile->write(EQEMuLog::Debug, "Fear Pathing: From (%.2f, %.2f, %.2f) small run to (%.2f, %.2f, %.2f)",
|
||||
GetX(), GetY(), GetZ(), cur_wp_x, cur_wp_y, cur_wp_z);
|
||||
#endif
|
||||
cur_wp_x = normalhit.x;
|
||||
cur_wp_y = normalhit.y;
|
||||
cur_wp_z = GetZ();
|
||||
|
||||
//try and fix up the Z coord if possible
|
||||
//not sure if this is worth it, since it prolly isnt up much
|
||||
|
||||
NodeRef c = zone->zonemap->SeekNode(zone->zonemap->GetRoot(), end.x, end.y);
|
||||
if(c != NODE_NONE) {
|
||||
cur_wp_z = zone->zonemap->FindBestZ(c, end, &hit, NULL);
|
||||
if(cur_wp_z < start.z)
|
||||
cur_wp_z = end.z; //revert on error
|
||||
}
|
||||
|
||||
CalculateNewPosition2(cur_wp_x, cur_wp_y, cur_wp_z, GetRunspeed(), true);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef FEAR_PATHING_DEBUG
|
||||
LogFile->write(EQEMuLog::Debug, "Fear Pathing: From (%.2f, %.2f, %.2f) normal hit at (%.2f, %.2f, %.2f)",
|
||||
GetX(), GetY(), GetZ(), normalhit.x, normalhit.y, normalhit.z);
|
||||
#endif
|
||||
|
||||
//if we get here, we cannot run along our normal vector...
|
||||
//try up hill first
|
||||
|
||||
/*
|
||||
while this uphill stuff works great in outdoor zones,
|
||||
it totally breaks dungeons...
|
||||
|
||||
float speed = GetRunspeed();
|
||||
end.x = start.x + fear_vector.x * speed;
|
||||
end.y = start.y + fear_vector.y * speed;
|
||||
end.z = start.z + speed + speed;
|
||||
|
||||
if(!zone->zonemap->LineIntersectsZone(start, end, 0.5, &hit, NULL)) {
|
||||
#ifdef FEAR_PATHING_DEBUG
|
||||
LogFile->write(EQEMuLog::Debug, "Fear Pathing: From (%.2f, %.2f, %.2f) up hill run to (%.2f, %.2f, %.2f)",
|
||||
GetX(), GetY(), GetZ(), end.x, end.y, end.z);
|
||||
#endif
|
||||
//we can run along this vector without hitting anything...
|
||||
cur_wp_x = end.x - 0.4 * fear_vector.x;
|
||||
cur_wp_y = end.y - 0.4 * fear_vector.y;
|
||||
cur_wp_z = end.z;
|
||||
|
||||
//try and fix up the Z coord if possible
|
||||
//not sure if this is worth it, since it prolly isnt up much
|
||||
|
||||
NodeRef c = zone->zonemap->SeekNode(zone->zonemap->GetRoot(), end.x, end.y);
|
||||
if(c != NODE_NONE) {
|
||||
cur_wp_z = zone->zonemap->FindBestZ(c, end, &hit, NULL);
|
||||
if(cur_wp_z < start.z)
|
||||
cur_wp_z = end.z; //revert on error
|
||||
}
|
||||
|
||||
|
||||
CalculateNewPosition2(cur_wp_x, cur_wp_y, cur_wp_z, GetRunspeed(), true);
|
||||
return;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
//cant run along our vector at all....
|
||||
//one last ditch effort... try to move to the side a little
|
||||
//along the minor component of the fear vector.
|
||||
//try it in one direction first...
|
||||
if(fear_vector.x < fear_vector.y) {
|
||||
end.x = start.x + fear_vector.x * 3;
|
||||
end.y = start.y;
|
||||
} else {
|
||||
end.x = start.x;
|
||||
end.y = start.y + fear_vector.y * 3;
|
||||
}
|
||||
end.z = start.z + 3; //a little lift as always
|
||||
|
||||
if(!zone->zonemap->LineIntersectsZone(start, end, 0.5, &hit, NULL)) {
|
||||
#ifdef FEAR_PATHING_DEBUG
|
||||
LogFile->write(EQEMuLog::Debug, "Fear Pathing: From (%.2f, %.2f, %.2f) strafe 1 to (%.2f, %.2f, %.2f)",
|
||||
GetX(), GetY(), GetZ(), end.x, end.y, end.z);
|
||||
#endif
|
||||
//we can run along this vector without hitting anything...
|
||||
cur_wp_x = end.x - 0.4 * fear_vector.x;
|
||||
cur_wp_y = end.y - 0.4 * fear_vector.y;
|
||||
cur_wp_z = end.z - 3;
|
||||
CalculateNewPosition2(cur_wp_x, cur_wp_y, cur_wp_z, GetRunspeed(), true);
|
||||
return;
|
||||
}
|
||||
|
||||
//now the other...
|
||||
if(fear_vector.x < fear_vector.y) {
|
||||
end.x = start.x + fear_vector.x * 3;
|
||||
end.y = start.y;
|
||||
} else {
|
||||
end.x = start.x;
|
||||
end.y = start.y + fear_vector.y * 3;
|
||||
}
|
||||
end.z = start.z + 3; //a little lift as always
|
||||
|
||||
if(!zone->zonemap->LineIntersectsZone(start, end, 0.5, &hit, NULL)) {
|
||||
#ifdef FEAR_PATHING_DEBUG
|
||||
LogFile->write(EQEMuLog::Debug, "Fear Pathing: From (%.2f, %.2f, %.2f) strafe 2 to (%.2f, %.2f, %.2f)",
|
||||
GetX(), GetY(), GetZ(), end.x, end.y, end.z);
|
||||
#endif
|
||||
//we can run along this vector without hitting anything...
|
||||
cur_wp_x = end.x - 0.4 * fear_vector.x;
|
||||
cur_wp_y = end.y - 0.4 * fear_vector.y;
|
||||
cur_wp_z = end.z - 3;
|
||||
CalculateNewPosition2(cur_wp_x, cur_wp_y, cur_wp_z, GetRunspeed(), true);
|
||||
return;
|
||||
}
|
||||
|
||||
//if we get here... we have wasted enough CPU cycles
|
||||
//just call it quits on fear pathing...
|
||||
|
||||
//send them to normalhit and then stop
|
||||
cur_wp_x = normalhit.x;
|
||||
cur_wp_y = normalhit.y;
|
||||
cur_wp_z = GetZ();
|
||||
fear_state = fearStateRunningToStick;
|
||||
#ifdef FEAR_PATHING_DEBUG
|
||||
LogFile->write(EQEMuLog::Debug, "Fear Pathing: From (%.2f, %.2f, %.2f) final move to (%.2f, %.2f, %.2f)",
|
||||
GetX(), GetY(), GetZ(), normalhit.x, normalhit.y, normalhit.z);
|
||||
#endif
|
||||
#endif //OLD_FEAR_PATHING
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+308
@@ -0,0 +1,308 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2004 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef FEATURES_H
|
||||
#define FEATURES_H
|
||||
|
||||
/*
|
||||
|
||||
This file defines many optional features for the emu
|
||||
as well as various parameters used by the emu.
|
||||
|
||||
If ambitious, most of these could prolly be turned into
|
||||
database variables, but the really frequently run pieces
|
||||
of code, should not be done that way for speed reasons IMO
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Core Zone features
|
||||
|
||||
*/
|
||||
|
||||
|
||||
//Uncomment this to cause a zone to basically idle
|
||||
//when there are no players in it, mobs stop wandering, etc..
|
||||
#define IDLE_WHEN_EMPTY
|
||||
|
||||
#ifdef EMBPERL
|
||||
//Enable the new XS based perl parser
|
||||
#define EMBPERL_XS
|
||||
|
||||
//enable classes in the new XS based parser
|
||||
#define EMBPERL_XS_CLASSES
|
||||
|
||||
//enable IO capture and transmission to in game clients
|
||||
//this seems to make perl very unhappy on reload, and crashes
|
||||
#define EMBPERL_IO_CAPTURE
|
||||
|
||||
//enable perl-based in-game command, pretty useless without EMBPERL_XS_CLASSES
|
||||
#define EMBPERL_COMMANDS
|
||||
|
||||
//enable #plugin and #peval, which requires IO::Stringy
|
||||
//#define EMBPERL_EVAL_COMMANDS
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
Map Configuration
|
||||
In general, these computations are expensive, so if you have performance
|
||||
problems, consider turning them off.
|
||||
|
||||
*/
|
||||
|
||||
//uncomment this to make the LOS code say all mobs can see all others
|
||||
//when no map file is loaded, opposed to the default nobody-sees-anybody
|
||||
#define LOS_DEFAULT_CAN_SEE
|
||||
|
||||
/*
|
||||
|
||||
Zone extensions and features
|
||||
|
||||
*/
|
||||
|
||||
//Uncomment this to scale XP gained from MOBs based on their CON
|
||||
//#define CON_XP_SCALING
|
||||
|
||||
//Uncomment to make group buffs affect group pets
|
||||
#define GROUP_BUFF_PETS
|
||||
|
||||
//Uncomment this line to enable named quest files:
|
||||
#define QUEST_SCRIPTS_BYNAME
|
||||
|
||||
#ifdef QUEST_SCRIPTS_BYNAME
|
||||
//extends byname system to look in a templates directory
|
||||
//independant of zone name
|
||||
#define QUEST_TEMPLATES_BYNAME
|
||||
#define QUEST_TEMPLATES_DIRECTORY "templates"
|
||||
#endif
|
||||
|
||||
//the min ratio at which a mob's speed is reduced
|
||||
#define FLEE_HP_MINSPEED 22
|
||||
//number of tics to try to run straight away before looking again
|
||||
#define FLEE_RUN_DURATION 1000
|
||||
//number of miliseconds between when a mob will check its flee state
|
||||
//this is only checked when the mob is damaged.
|
||||
#define FLEE_CHECK_TIMER 2000
|
||||
|
||||
//enable functionality to send log message to the client
|
||||
//it still needs to be enabled with the #logs command
|
||||
#define CLIENT_LOGS
|
||||
|
||||
//uncomment to print warnings about commands with 0 status...
|
||||
//#define COMMANDS_WARNINGS
|
||||
|
||||
//uncomment to allow perl commands to override compiled commands
|
||||
#define COMMANDS_PERL_OVERRIDE
|
||||
|
||||
//enable logging of commands used
|
||||
#define COMMANDS_LOGGING
|
||||
|
||||
//only log commands which require this minimum status or more
|
||||
#define COMMANDS_LOGGING_MIN_STATUS 1
|
||||
|
||||
//path to where sql logs should be placed
|
||||
#define SQL_LOG_PATH "sql_logs/"
|
||||
|
||||
//New aggro system to reduce overhead.
|
||||
#define REVERSE_AGGRO
|
||||
|
||||
//Enable spacial queue to manage NPC update packets
|
||||
//#define PACKET_UPDATE_MANAGER
|
||||
//#define MANAGE_HP_UPDATES
|
||||
|
||||
//The highest you can #setskill / #setallskill
|
||||
#define HIGHEST_CAN_SET_SKILL 400
|
||||
|
||||
#define SKILL_MAX_LEVEL 75
|
||||
|
||||
//#define MIN_RANGED_ATK_RANGE 25
|
||||
//replaced the above define with RuleI(Combat, MinRangedAttackDist)
|
||||
|
||||
/*
|
||||
|
||||
Zone Numerical configuration
|
||||
|
||||
*/
|
||||
|
||||
//Reuse times for various skills, here for convenience, in sec
|
||||
//set to 0 to disable server side checking of timers.
|
||||
enum { //reuse times
|
||||
FeignDeathReuseTime = 9,
|
||||
SneakReuseTime = 7,
|
||||
HideReuseTime = 8,
|
||||
TauntReuseTime = 5,
|
||||
InstillDoubtReuseTime = 9,
|
||||
FishingReuseTime = 11,
|
||||
ForagingReuseTime = 50,
|
||||
MendReuseTime = 290,
|
||||
BashReuseTime = 5,
|
||||
BackstabReuseTime = 9,
|
||||
KickReuseTime = 5,
|
||||
TailRakeReuseTime = 6,
|
||||
EagleStrikeReuseTime = 5,
|
||||
RoundKickReuseTime = 9,
|
||||
TigerClawReuseTime = 6,
|
||||
FlyingKickReuseTime = 7,
|
||||
SenseTrapsReuseTime = 9,
|
||||
DisarmTrapsReuseTime = 9,
|
||||
HarmTouchReuseTime = 4300,
|
||||
LayOnHandsReuseTime = 4300,
|
||||
FrenzyReuseTime = 10
|
||||
};
|
||||
|
||||
enum { //timer settings, all in milliseconds
|
||||
AImovement_duration = 100,
|
||||
AIthink_duration = 150,
|
||||
AIscanarea_delay = 500,
|
||||
AIfeignremember_delay = 500,
|
||||
AItarget_check_duration = 500,
|
||||
AIClientScanarea_delay = 750, //used in REVERSE_AGGRO
|
||||
AIassistcheck_delay = 3000, //now often a fighting NPC will yell for help
|
||||
ClientProximity_interval = 1000,
|
||||
CombatEventTimer_expire = 12000,
|
||||
Tribute_duration = 600000,
|
||||
ZoneTimerResolution = 3, //sleep time between zone main loop runs (milliseconds)
|
||||
FeignMemoryDuration = 120000, // EverHood - Duration player must feign death to clear zonewide agro.
|
||||
EnragedTimer = 360000,
|
||||
EnragedDurationTimer = 10000
|
||||
};
|
||||
|
||||
enum { //some random constants
|
||||
//each of these attack modifiers are added to the NPC's level to determine their
|
||||
//probability of executing such an attack (which may or may not hit)
|
||||
NPCDualAttackModifier = 20,
|
||||
NPCTripleAttackModifier = 0,
|
||||
NPCQuadAttackModifier = -20
|
||||
};
|
||||
|
||||
//Max number of groups you can link with. Not tied to the client.
|
||||
//if group linking is enabled above
|
||||
#define MAX_GROUP_LINKS 8
|
||||
|
||||
//this is the number of levels above the thief's level that
|
||||
//an npc can be and still let the theif PP them
|
||||
#define THIEF_PICKPOCKET_OVER 5
|
||||
|
||||
//this is the % chance that an NPC will dual wield a 2nd weapon
|
||||
//in its loot table, if it is able to.
|
||||
//Aug 2007: was 5% chance.. changed to 100% by default since that seems more normal
|
||||
//Kept it intact codewise incase someone wants to or is already using it.
|
||||
#define NPC_DW_CHANCE 100
|
||||
|
||||
//This is the entry in npc_types to spawn for trap damagaes
|
||||
#define TRAP_NPC_TYPE 1586
|
||||
|
||||
//This is the multiplier of eqemu speed to get client speed
|
||||
//tweak this if pathing mobs seem to jump forward or backwards
|
||||
//this should prolly be dynamic based on ping time or something.. who knows
|
||||
//Values found in the emu somewhere at one point in time: 36, 43
|
||||
#define NPC_RUNANIM_RATIO 37
|
||||
|
||||
//this is used to multiply an NPCs movement rate, yeilding map units..
|
||||
#define NPC_SPEED_MULTIPLIER 46 //used to be 2.8... no idea why it changed
|
||||
|
||||
//minimum level to do alchemy
|
||||
#define MIN_LEVEL_ALCHEMY 25
|
||||
|
||||
//chance ratio that a
|
||||
#define THREATENLY_ARRGO_CHANCE 32 // 32/128 (25%) chance that a mob will arrgo on con Threatenly
|
||||
|
||||
// max factions per npc faction list
|
||||
#define MAX_NPC_FACTIONS 20
|
||||
|
||||
//value caps
|
||||
#define MAX_FACTION 1500
|
||||
#define MIN_FACTION -1500
|
||||
|
||||
//The Level Cap:
|
||||
//#define LEVEL_CAP RuleI(Character, MaxLevel) //hard cap is 127
|
||||
#define HARD_LEVEL_CAP 127
|
||||
|
||||
//the square of the maximum range at whihc you could possibly use NPC services (shop, tribute, etc)
|
||||
#define USE_NPC_RANGE2 200*200 //arbitrary right now
|
||||
|
||||
//the formula for experience for killing a mob.
|
||||
//level is the only valid variable to use
|
||||
#define EXP_FORMULA level*level*75*35/10
|
||||
|
||||
#define HIGHEST_AA_VALUE 35
|
||||
|
||||
//Leadership AA experience points
|
||||
#define GROUP_EXP_PER_POINT 1000
|
||||
#define RAID_EXP_PER_POINT 2000
|
||||
|
||||
//Some hard coded statuses from commands and other places:
|
||||
enum {
|
||||
minStatusToBeGM = 40,
|
||||
minStatusToUseGMCommands = 80,
|
||||
minStatusToKick = 150,
|
||||
minStatusToAvoidFalling = 100,
|
||||
minStatusToHaveInvalidSpells = 80,
|
||||
minStatusToHaveInvalidSkills = 80,
|
||||
minStatusToIgnoreZoneFlags = 80,
|
||||
minStatusToSeeOthersZoneFlags = 80,
|
||||
minStatusToEditOtherGuilds = 80,
|
||||
commandMovecharSelfOnly = 80, //below this == only self move allowed
|
||||
commandMovecharToSpecials = 200, //ability to send people to cshom/load zones
|
||||
commandZoneToSpecials = 80, //zone to cshome, out of load zones
|
||||
commandToggleAI = 250, //can turn NPC AI on and off
|
||||
commandCastSpecials = 100, //can cast special spells
|
||||
commandInstacast = 100, //insta-cast all #casted spells
|
||||
commandLevelAboveCap = 100, //can #level players above level cap
|
||||
commandLevelNPCAboveCap = 100, //can #level NPCs above level cap
|
||||
commandSetSkillsOther = 100, //ability to setskills on others
|
||||
commandRaceOthers = 100, //ability to #race on others
|
||||
commandGenderOthers = 100, //ability to #gender on others
|
||||
commandTextureOthers = 100, //ability to #texture on others
|
||||
commandDoAnimOthers = 100, //can #doanim on others
|
||||
commandLockZones = 101, //can lock or unlock zones
|
||||
commandEditPlayerCorpses = 150, //can Edit Player Corpses
|
||||
commandChangeFlags = 200, //ability to set/refresh flags
|
||||
commandBanPlayers = 100, //can set bans on players
|
||||
commandChangeDatarate = 201, //edit client's data rate
|
||||
commandZoneToCoords = 0 //can #zone with coords
|
||||
};
|
||||
|
||||
//default states for logging flag on NPCs and clients (having NPCs on by default is prolly a bad idea)
|
||||
#define CLIENT_DEFAULT_LOGGING_ENABLED true
|
||||
#define NPC_DEFAULT_LOGGING_ENABLED false
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Developer configuration
|
||||
|
||||
*/
|
||||
|
||||
//#define EQPROFILE
|
||||
#ifdef EQPROFILE
|
||||
//Enable the zone profiler
|
||||
#define ZONE_PROFILE
|
||||
|
||||
#define COMMON_PROFILE
|
||||
|
||||
#define PROFILE_DUMP_TIME 3*60
|
||||
#endif //EQPROFILE
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
+487
@@ -0,0 +1,487 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "../common/debug.h"
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#include "forage.h"
|
||||
#include "entity.h"
|
||||
#include "masterentity.h"
|
||||
#include "npc.h"
|
||||
#include "watermap.h"
|
||||
#include "titles.h"
|
||||
#include "StringIDs.h"
|
||||
#include "../common/MiscFunctions.h"
|
||||
#include "../common/rulesys.h"
|
||||
|
||||
#include "zonedb.h"
|
||||
#ifdef _WINDOWS
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#include "QuestParserCollection.h"
|
||||
|
||||
//max number of items which can be in the foraging table
|
||||
//for a given zone.
|
||||
#define FORAGE_ITEM_LIMIT 50
|
||||
|
||||
/*
|
||||
|
||||
The fishing and foraging need some work...
|
||||
foraging currently gives each item an equal chance of dropping
|
||||
fishing gives items which come in last from the select a very
|
||||
very low chance of dropping.
|
||||
|
||||
|
||||
Schema:
|
||||
CREATE TABLE forage (
|
||||
id int(11) NOT NULL auto_increment,
|
||||
zoneid int(4) NOT NULL default '0',
|
||||
Itemid int(11) NOT NULL default '0',
|
||||
level smallint(6) NOT NULL default '0',
|
||||
chance smallint(6) NOT NULL default '0',
|
||||
PRIMARY KEY (id)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
old table upgrade:
|
||||
alter table forage add chance smallint(6) NOT NULL default '0';
|
||||
update forage set chance=100;
|
||||
|
||||
|
||||
CREATE TABLE fishing (
|
||||
id int(11) NOT NULL auto_increment,
|
||||
zoneid int(4) NOT NULL default '0',
|
||||
Itemid int(11) NOT NULL default '0',
|
||||
skill_level smallint(6) NOT NULL default '0',
|
||||
chance smallint(6) NOT NULL default '0',
|
||||
npc_id int NOT NULL default 0,
|
||||
npc_chance int NOT NULL default 0,
|
||||
PRIMARY KEY (id)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
|
||||
*/
|
||||
|
||||
// This allows EqEmu to have zone specific foraging - BoB
|
||||
uint32 ZoneDatabase::GetZoneForage(uint32 ZoneID, uint8 skill) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
uint8 index = 0;
|
||||
uint32 item[FORAGE_ITEM_LIMIT];
|
||||
uint32 chance[FORAGE_ITEM_LIMIT];
|
||||
uint32 ret;
|
||||
|
||||
for (int c=0; c < FORAGE_ITEM_LIMIT; c++) {
|
||||
item[c] = 0;
|
||||
}
|
||||
|
||||
uint32 chancepool = 0;
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT itemid,chance FROM forage WHERE zoneid= '%i' and level <= '%i' LIMIT %i", ZoneID, skill, FORAGE_ITEM_LIMIT), errbuf, &result))
|
||||
{
|
||||
safe_delete_array(query);
|
||||
while ((row = mysql_fetch_row(result)) && (index < FORAGE_ITEM_LIMIT)) {
|
||||
item[index] = atoi(row[0]);
|
||||
chance[index] = atoi(row[1])+chancepool;
|
||||
LogFile->write(EQEMuLog::Error, "Possible Forage: %d with a %d chance", item[index], chance[index]);
|
||||
chancepool = chance[index];
|
||||
index++;
|
||||
}
|
||||
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in Forage query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(chancepool == 0 || index < 1)
|
||||
return(0);
|
||||
|
||||
if(index == 1) {
|
||||
return(item[0]);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
uint32 rindex = MakeRandomInt(1, chancepool);
|
||||
|
||||
for(int i = 0; i < index; i++) {
|
||||
if(rindex <= chance[i]) {
|
||||
ret = item[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32 ZoneDatabase::GetZoneFishing(uint32 ZoneID, uint8 skill, uint32 &npc_id, uint8 &npc_chance)
|
||||
{
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
uint8 index = 0;
|
||||
uint32 item[50];
|
||||
uint32 chance[50];
|
||||
uint32 npc_ids[50];
|
||||
uint32 npc_chances[50];
|
||||
uint32 chancepool = 0;
|
||||
uint32 ret = 0;
|
||||
|
||||
for (int c=0; c<50; c++) {
|
||||
item[c]=0;
|
||||
chance[c]=0;
|
||||
}
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT itemid,chance,npc_id,npc_chance FROM fishing WHERE (zoneid= '%i' || zoneid = 0) and skill_level <= '%i'",ZoneID, skill ), errbuf, &result))
|
||||
{
|
||||
safe_delete_array(query);
|
||||
while ((row = mysql_fetch_row(result))&&(index<50)) {
|
||||
item[index] = atoi(row[0]);
|
||||
chance[index] = atoi(row[1])+chancepool;
|
||||
chancepool = chance[index];
|
||||
|
||||
npc_ids[index] = atoi(row[2]);
|
||||
npc_chances[index] = atoi(row[3]);
|
||||
index++;
|
||||
}
|
||||
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else {
|
||||
cerr << "Error in Fishing query '" << query << "' " << errbuf << endl;
|
||||
safe_delete_array(query);
|
||||
return 0;
|
||||
}
|
||||
|
||||
npc_id = 0;
|
||||
npc_chance = 0;
|
||||
if (index>0) {
|
||||
uint32 random = MakeRandomInt(1, chancepool);
|
||||
for (int i = 0; i < index; i++)
|
||||
{
|
||||
if (random <= chance[i])
|
||||
{
|
||||
ret = item[i];
|
||||
npc_id = npc_ids[i];
|
||||
npc_chance = npc_chances[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//we need this function to immediately determine, after we receive OP_Fishing, if we can even try to fish, otherwise we have to wait a while to get the failure
|
||||
bool Client::CanFish() {
|
||||
//make sure we still have a fishing pole on:
|
||||
const ItemInst* Pole = m_inv[SLOT_PRIMARY];
|
||||
int32 bslot = m_inv.HasItemByUse(ItemTypeFishingBait, 1, invWhereWorn|invWherePersonal);
|
||||
const ItemInst* Bait = NULL;
|
||||
if(bslot != SLOT_INVALID)
|
||||
Bait = m_inv.GetItem(bslot);
|
||||
|
||||
if(!Pole || !Pole->IsType(ItemClassCommon) || Pole->GetItem()->ItemType != ItemTypeFishingPole) {
|
||||
if (m_inv.HasItemByUse(ItemTypeFishingPole, 1, invWhereWorn|invWherePersonal|invWhereBank|invWhereSharedBank|invWhereTrading|invWhereCursor)) //We have a fishing pole somewhere, just not equipped
|
||||
Message_StringID(MT_Skills, FISHING_EQUIP_POLE); //You need to put your fishing pole in your primary hand.
|
||||
else //We don't have a fishing pole anywhere
|
||||
Message_StringID(MT_Skills, FISHING_NO_POLE); //You can't fish without a fishing pole, go buy one.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Bait || !Bait->IsType(ItemClassCommon) || Bait->GetItem()->ItemType != ItemTypeFishingBait) {
|
||||
Message_StringID(MT_Skills, FISHING_NO_BAIT); //You can't fish without fishing bait, go buy some.
|
||||
return false;
|
||||
}
|
||||
|
||||
if(zone->zonemap!=NULL && zone->watermap != NULL && RuleB(Watermap, CheckForWaterWhenFishing)) {
|
||||
float RodX, RodY, RodZ;
|
||||
// Tweak Rod and LineLength if required
|
||||
const float RodLength = RuleR(Watermap, FishingRodLength);
|
||||
const float LineLength = RuleR(Watermap, FishingLineLength);
|
||||
int HeadingDegrees;
|
||||
|
||||
HeadingDegrees = (int) ((GetHeading()*360)/256);
|
||||
HeadingDegrees = HeadingDegrees % 360;
|
||||
|
||||
RodX = x_pos + RodLength * sin(HeadingDegrees * M_PI/180.0f);
|
||||
RodY = y_pos + RodLength * cos(HeadingDegrees * M_PI/180.0f);
|
||||
|
||||
// Do BestZ to find where the line hanging from the rod intersects the water (if it is water).
|
||||
// and go 1 unit into the water.
|
||||
VERTEX dest;
|
||||
dest.x = RodX;
|
||||
dest.y = RodY;
|
||||
dest.z = z_pos+10;
|
||||
NodeRef n = zone->zonemap->SeekNode( zone->zonemap->GetRoot(), dest.x, dest.y);
|
||||
if(n != NODE_NONE) {
|
||||
RodZ = zone->zonemap->FindBestZ(n, dest, NULL, NULL) - 1;
|
||||
bool in_lava = zone->watermap->InLava(RodX, RodY, RodZ);
|
||||
bool in_water = zone->watermap->InWater(RodX, RodY, RodZ) || zone->watermap->InVWater(RodX, RodY, RodZ);
|
||||
//Message(0, "Rod is at %4.3f, %4.3f, %4.3f, InWater says %d, InLava says %d", RodX, RodY, RodZ, in_water, in_lava);
|
||||
if (in_lava) {
|
||||
Message_StringID(MT_Skills, FISHING_LAVA); //Trying to catch a fire elemental or something?
|
||||
return false;
|
||||
}
|
||||
if((!in_water) || (z_pos-RodZ)>LineLength) { //Didn't hit the water OR the water is too far below us
|
||||
Message_StringID(MT_Skills, FISHING_LAND); //Trying to catch land sharks perhaps?
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Client::GoFish()
|
||||
{
|
||||
|
||||
//TODO: generate a message if we're already fishing
|
||||
/*if (!fishing_timer.Check()) { //this isn't the right check, may need to add something to the Client class like 'bool is_fishing'
|
||||
Message_StringID(0, ALREADY_FISHING); //You are already fishing!
|
||||
return;
|
||||
}*/
|
||||
|
||||
fishing_timer.Disable();
|
||||
|
||||
//we're doing this a second time (1st in Client::Handle_OP_Fishing) to make sure that, between when we started fishing & now, we're still able to fish (in case we move, change equip, etc)
|
||||
if (!CanFish()) //if we can't fish here, we don't need to bother with the rest
|
||||
return;
|
||||
|
||||
//multiple entries yeilds higher probability of dropping...
|
||||
uint32 common_fish_ids[MAX_COMMON_FISH_IDS] = {
|
||||
1038, // Tattered Cloth Sandals
|
||||
1038, // Tattered Cloth Sandals
|
||||
1038, // Tattered Cloth Sandals
|
||||
13019, // Fresh Fish
|
||||
13076, // Fish Scales
|
||||
13076, // Fish Scales
|
||||
7007, // Rusty Dagger
|
||||
7007, // Rusty Dagger
|
||||
7007 // Rusty Dagger
|
||||
|
||||
};
|
||||
|
||||
//success formula is not researched at all
|
||||
|
||||
int fishing_skill = GetSkill(FISHING); //will take into account skill bonuses on pole & bait
|
||||
|
||||
//make sure we still have a fishing pole on:
|
||||
int32 bslot = m_inv.HasItemByUse(ItemTypeFishingBait, 1, invWhereWorn|invWherePersonal);
|
||||
const ItemInst* Bait = NULL;
|
||||
if(bslot != SLOT_INVALID)
|
||||
Bait = m_inv.GetItem(bslot);
|
||||
|
||||
//if the bait isnt equipped, need to add its skill bonus
|
||||
if(bslot >= IDX_INV && Bait->GetItem()->SkillModType == FISHING) {
|
||||
fishing_skill += Bait->GetItem()->SkillModValue;
|
||||
}
|
||||
|
||||
if (fishing_skill > 100)
|
||||
{
|
||||
fishing_skill = 100+((fishing_skill-100)/2);
|
||||
}
|
||||
|
||||
if (MakeRandomInt(0,175) < fishing_skill) {
|
||||
uint32 food_id = 0;
|
||||
|
||||
//25% chance to fish an item.
|
||||
if (MakeRandomInt(0, 399) <= fishing_skill ) {
|
||||
uint32 npc_id = 0;
|
||||
uint8 npc_chance = 0;
|
||||
food_id = database.GetZoneFishing(m_pp.zone_id, fishing_skill, npc_id, npc_chance);
|
||||
|
||||
//check for add NPC
|
||||
if(npc_chance > 0 && npc_id) {
|
||||
if(npc_chance < MakeRandomInt(0, 99)) {
|
||||
const NPCType* tmp = database.GetNPCType(npc_id);
|
||||
if(tmp != NULL) {
|
||||
NPC* npc = new NPC(tmp, NULL, GetX()+3, GetY(), GetZ(), GetHeading(), FlyMode3);
|
||||
npc->AddLootTable();
|
||||
|
||||
npc->AddToHateList(this, 1, 0, false); //no help yelling
|
||||
|
||||
entity_list.AddNPC(npc);
|
||||
|
||||
Message(MT_Emote, "You fish up a little more than you bargained for...");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//consume bait, should we always consume bait on success?
|
||||
DeleteItemInInventory(bslot, 1, true); //do we need client update?
|
||||
|
||||
if(food_id == 0) {
|
||||
int index = MakeRandomInt(0, MAX_COMMON_FISH_IDS-1);
|
||||
food_id = common_fish_ids[index];
|
||||
}
|
||||
|
||||
const Item_Struct* food_item = database.GetItem(food_id);
|
||||
|
||||
Message_StringID(MT_Skills, FISHING_SUCCESS);
|
||||
const ItemInst* inst = database.CreateItem(food_item, 1);
|
||||
if(inst != NULL) {
|
||||
if(CheckLoreConflict(inst->GetItem()))
|
||||
{
|
||||
this->Message_StringID(0,DUP_LORE);
|
||||
}
|
||||
else
|
||||
{
|
||||
PushItemOnCursor(*inst); // changed from PutItemInInventory(SLOT_CURSOR, *inst); - was additional overhead
|
||||
SendItemPacket(SLOT_CURSOR,inst,ItemPacketSummonItem);
|
||||
if(RuleB(TaskSystem, EnableTaskSystem))
|
||||
UpdateTasksForItem(ActivityFish, food_id);
|
||||
}
|
||||
safe_delete(inst);
|
||||
}
|
||||
|
||||
parse->EventPlayer(EVENT_FISH_SUCCESS, this, "", inst != NULL ? inst->GetItem()->ID : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
//chance to use bait when you dont catch anything...
|
||||
if (MakeRandomInt(0, 4) == 1) {
|
||||
DeleteItemInInventory(bslot, 1, true); //do we need client update?
|
||||
Message_StringID(MT_Skills, FISHING_LOST_BAIT); //You lost your bait!
|
||||
} else {
|
||||
if (MakeRandomInt(0, 15) == 1) //give about a 1 in 15 chance to spill your beer. we could make this a rule, but it doesn't really seem worth it
|
||||
//TODO: check for & consume an alcoholic beverage from inventory when this triggers, and set it as a rule that's disabled by default
|
||||
Message_StringID(MT_Skills, FISHING_SPILL_BEER); //You spill your beer while bringing in your line.
|
||||
else
|
||||
Message_StringID(MT_Skills, FISHING_FAILED); //You didn't catch anything.
|
||||
}
|
||||
|
||||
parse->EventPlayer(EVENT_FISH_FAILURE, this, "", 0);
|
||||
}
|
||||
|
||||
//chance to break fishing pole...
|
||||
//this is potentially exploitable in that they can fish
|
||||
//and then swap out items in primary slot... too lazy to fix right now
|
||||
if (MakeRandomInt(0, 49) == 1) {
|
||||
Message_StringID(MT_Skills, FISHING_POLE_BROKE); //Your fishing pole broke!
|
||||
DeleteItemInInventory(13,0,true);
|
||||
}
|
||||
|
||||
if(CheckIncreaseSkill(FISHING, NULL, 5))
|
||||
{
|
||||
if(title_manager.IsNewTradeSkillTitleAvailable(FISHING, GetRawSkill(FISHING)))
|
||||
NotifyNewTitlesAvailable();
|
||||
}
|
||||
}
|
||||
|
||||
void Client::ForageItem() {
|
||||
|
||||
int skill_level = GetSkill(FORAGE);
|
||||
|
||||
//be wary of the string ids in switch below when changing this.
|
||||
uint32 common_food_ids[MAX_COMMON_FOOD_IDS] = {
|
||||
13046, // Fruit
|
||||
13045, // Berries
|
||||
13419, // Vegetables
|
||||
13048, // Rabbit Meat
|
||||
13047, // Roots
|
||||
13044, // Pod Of Water
|
||||
14905, // mushroom
|
||||
13106 // Fishing Grubs
|
||||
};
|
||||
|
||||
// these may need to be fine tuned, I am just guessing here
|
||||
if (MakeRandomInt(0,199) < skill_level) {
|
||||
uint32 foragedfood = 0;
|
||||
uint32 stringid = FORAGE_NOEAT;
|
||||
|
||||
if (MakeRandomInt(0,99) <= 25) {
|
||||
foragedfood = database.GetZoneForage(m_pp.zone_id, skill_level);
|
||||
}
|
||||
|
||||
//not an else in case theres no DB food
|
||||
if(foragedfood == 0) {
|
||||
uint8 index = 0;
|
||||
index = MakeRandomInt(0, MAX_COMMON_FOOD_IDS-1);
|
||||
foragedfood = common_food_ids[index];
|
||||
}
|
||||
|
||||
const Item_Struct* food_item = database.GetItem(foragedfood);
|
||||
|
||||
if(!food_item) {
|
||||
LogFile->write(EQEMuLog::Error, "NULL returned from database.GetItem in ClientForageItem");
|
||||
return;
|
||||
}
|
||||
|
||||
if(foragedfood == 13106)
|
||||
stringid = FORAGE_GRUBS;
|
||||
else
|
||||
switch(food_item->ItemType) {
|
||||
|
||||
case ItemTypeFood:
|
||||
stringid = FORAGE_FOOD;
|
||||
break;
|
||||
|
||||
case ItemTypeDrink:
|
||||
if(strstr(food_item->Name, "ater"))
|
||||
stringid = FORAGE_WATER;
|
||||
else
|
||||
stringid = FORAGE_DRINK;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Message_StringID(MT_Skills, stringid);
|
||||
const ItemInst* inst = database.CreateItem(food_item, 1);
|
||||
if(inst != NULL) {
|
||||
// check to make sure it isn't a foraged lore item
|
||||
if(CheckLoreConflict(inst->GetItem()))
|
||||
{
|
||||
this->Message_StringID(0,DUP_LORE);
|
||||
}
|
||||
else {
|
||||
PushItemOnCursor(*inst);
|
||||
SendItemPacket(SLOT_CURSOR, inst, ItemPacketSummonItem);
|
||||
if(RuleB(TaskSystem, EnableTaskSystem))
|
||||
UpdateTasksForItem(ActivityForage, foragedfood);
|
||||
}
|
||||
safe_delete(inst);
|
||||
}
|
||||
|
||||
parse->EventPlayer(EVENT_FORAGE_SUCCESS, this, "", inst != NULL ? inst->GetItem()->ID : 0);
|
||||
|
||||
} else {
|
||||
Message_StringID(MT_Skills, FORAGE_FAILED);
|
||||
parse->EventPlayer(EVENT_FORAGE_FAILURE, this, "", 0);
|
||||
}
|
||||
|
||||
CheckIncreaseSkill(FORAGE, NULL, 5);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef FORAGE_H
|
||||
#define FORAGE_H
|
||||
#include "../common/types.h"
|
||||
|
||||
#define MAX_COMMON_FOOD_IDS 8
|
||||
#define MAX_COMMON_FISH_IDS 9
|
||||
|
||||
#endif
|
||||
+2134
File diff suppressed because it is too large
Load Diff
+156
@@ -0,0 +1,156 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef GROUPS_H
|
||||
#define GROUPS_H
|
||||
|
||||
#include "../common/types.h"
|
||||
#include "../common/linked_list.h"
|
||||
#include "../common/emu_opcodes.h"
|
||||
#include "../common/eq_packet_structs.h"
|
||||
#include "entity.h"
|
||||
#include "mob.h"
|
||||
#include "features.h"
|
||||
#include "../common/servertalk.h"
|
||||
|
||||
#define MAX_MARKED_NPCS 3
|
||||
|
||||
enum { RoleAssist = 1, RoleTank = 2, RolePuller = 4 };
|
||||
|
||||
class GroupIDConsumer {
|
||||
public:
|
||||
GroupIDConsumer() { id = 0; }
|
||||
GroupIDConsumer(uint32 gid) { id = gid; }
|
||||
inline const uint32 GetID() const { return id; }
|
||||
|
||||
protected:
|
||||
friend class EntityList;
|
||||
//use of this function is highly discouraged
|
||||
inline void SetID(uint32 set_id) { id = set_id; }
|
||||
private:
|
||||
uint32 id;
|
||||
};
|
||||
|
||||
class Group : public GroupIDConsumer {
|
||||
public:
|
||||
Group(Mob* leader);
|
||||
Group(uint32 gid);
|
||||
~Group();
|
||||
|
||||
bool AddMember(Mob* newmember, const char* NewMemberName = NULL, uint32 CharacterID = 0);
|
||||
void AddMember(const char* NewMemberName);
|
||||
void SendUpdate(uint32 type,Mob* member);
|
||||
void SendLeadershipAAUpdate();
|
||||
void SendWorldGroup(uint32 zone_id,Mob* zoningmember);
|
||||
bool DelMemberOOZ(const char *Name);
|
||||
bool DelMember(Mob* oldmember,bool ignoresender = false);
|
||||
void DisbandGroup();
|
||||
bool IsGroupMember(Mob* client);
|
||||
bool IsGroupMember(const char *Name);
|
||||
bool Process();
|
||||
bool IsGroup() { return true; }
|
||||
void CastGroupSpell(Mob* caster,uint16 spellid);
|
||||
void GroupBardPulse(Mob* caster,uint16 spellid);
|
||||
void SplitExp(uint32 exp, Mob* other);
|
||||
void GroupMessage(Mob* sender,uint8 language,uint8 lang_skill,const char* message);
|
||||
void GroupMessage_StringID(Mob* sender, uint32 type, uint32 string_id, const char* message,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0, uint32 distance = 0);
|
||||
uint32 GetTotalGroupDamage(Mob* other);
|
||||
void SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter = NULL);
|
||||
inline void SetLeader(Mob* newleader){ leader=newleader; };
|
||||
inline Mob* GetLeader(){ return leader; };
|
||||
char* GetLeaderName() { return membername[0]; };
|
||||
void SendHPPacketsTo(Mob* newmember);
|
||||
void SendHPPacketsFrom(Mob* newmember);
|
||||
bool UpdatePlayer(Mob* update);
|
||||
void MemberZoned(Mob* removemob);
|
||||
inline bool IsLeader(Mob* leadertest) { return leadertest==leader; };
|
||||
uint8 GroupCount();
|
||||
uint32 GetHighestLevel();
|
||||
uint32 GetLowestLevel();
|
||||
void QueuePacket(const EQApplicationPacket *app, bool ack_req = true);
|
||||
void TeleportGroup(Mob* sender, uint32 zoneID, uint16 instance_id, float x, float y, float z, float heading);
|
||||
uint16 GetAvgLevel();
|
||||
bool LearnMembers();
|
||||
void VerifyGroup();
|
||||
void BalanceHP(int32 penalty);
|
||||
void BalanceMana(int32 penalty);
|
||||
void HealGroup(uint32 heal_amt, Mob* caster);
|
||||
inline void SetGroupAAs(GroupLeadershipAA_Struct *From) { memcpy(&LeaderAbilities, From, sizeof(GroupLeadershipAA_Struct)); }
|
||||
inline void GetGroupAAs(GroupLeadershipAA_Struct *Into) { memcpy(Into, &LeaderAbilities, sizeof(GroupLeadershipAA_Struct)); }
|
||||
void UpdateGroupAAs();
|
||||
void SaveGroupLeaderAA();
|
||||
void MarkNPC(Mob* Target, int Number);
|
||||
int8 GetNumberNeedingHealedInGroup(int8 hpr, bool includePets);
|
||||
void DelegateMainTank(const char *NewMainAssistName, uint8 toggle = 0);
|
||||
void DelegateMainAssist(const char *NewMainAssistName, uint8 toggle = 0);
|
||||
void DelegatePuller(const char *NewMainAssistName, uint8 toggle = 0);
|
||||
void UnDelegateMainTank(const char *OldMainAssistName, uint8 toggle = 0);
|
||||
void UnDelegateMainAssist(const char *OldMainAssistName, uint8 toggle = 0);
|
||||
void UnDelegatePuller(const char *OldMainAssistName, uint8 toggle = 0);
|
||||
bool IsNPCMarker(Client *c);
|
||||
void SetGroupAssistTarget(Mob *m);
|
||||
void SetGroupTankTarget(Mob *m);
|
||||
void SetGroupPullerTarget(Mob *m);
|
||||
bool HasRole(Mob *m, uint8 Role);
|
||||
void NotifyAssistTarget(Client *c);
|
||||
void NotifyTankTarget(Client *c);
|
||||
void NotifyPullerTarget(Client *c);
|
||||
void DelegateMarkNPC(const char *NewNPCMarkerName);
|
||||
void UnDelegateMarkNPC(const char *OldNPCMarkerName);
|
||||
void NotifyMainTank(Client *c, uint8 toggle = 0);
|
||||
void NotifyMainAssist(Client *c, uint8 toggle = 0);
|
||||
void NotifyPuller(Client *c, uint8 toggle = 0);
|
||||
void NotifyMarkNPC(Client *c);
|
||||
inline uint32 GetNPCMarkerID() { return NPCMarkerID; }
|
||||
void SetMainTank(const char *NewMainTankName);
|
||||
void SetMainAssist(const char *NewMainAssistName);
|
||||
void SetPuller(const char *NewPullerName);
|
||||
const char *GetMainTankName() { return MainTankName.c_str(); }
|
||||
const char *GetMainAssistName() { return MainAssistName.c_str(); }
|
||||
const char *GetPullerName() { return PullerName.c_str(); }
|
||||
void SetNPCMarker(const char *NewNPCMarkerName);
|
||||
void UnMarkNPC(uint16 ID);
|
||||
void SendMarkedNPCsToMember(Client *c, bool Clear = false);
|
||||
inline int GetLeadershipAA(int AAID) { return LeaderAbilities.ranks[AAID]; }
|
||||
void ClearAllNPCMarks();
|
||||
void QueueHPPacketsForNPCHealthAA(Mob* sender, const EQApplicationPacket* app);
|
||||
void ChangeLeader(Mob* newleader);
|
||||
const char *GetClientNameByIndex(uint8 index);
|
||||
void UpdateXTargetMarkedNPC(uint32 Number, Mob *m);
|
||||
|
||||
Mob* members[MAX_GROUP_MEMBERS];
|
||||
char membername[MAX_GROUP_MEMBERS][64];
|
||||
uint8 MemberRoles[MAX_GROUP_MEMBERS];
|
||||
bool disbandcheck;
|
||||
bool castspell;
|
||||
|
||||
private:
|
||||
Mob* leader;
|
||||
GroupLeadershipAA_Struct LeaderAbilities;
|
||||
string MainTankName;
|
||||
string MainAssistName;
|
||||
string PullerName;
|
||||
string NPCMarkerName;
|
||||
uint16 NPCMarkerID;
|
||||
uint16 AssistTargetID;
|
||||
uint16 TankTargetID;
|
||||
uint16 PullerTargetID;
|
||||
uint16 MarkedNPCs[MAX_MARKED_NPCS];
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
+434
@@ -0,0 +1,434 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "../common/debug.h"
|
||||
#include "masterentity.h"
|
||||
#include "worldserver.h"
|
||||
#include "net.h"
|
||||
#include "../common/database.h"
|
||||
#include "spdat.h"
|
||||
#include "../common/packet_dump.h"
|
||||
#include "../common/packet_functions.h"
|
||||
#include "petitions.h"
|
||||
#include "../common/serverinfo.h"
|
||||
#include "../common/ZoneNumbers.h"
|
||||
#include "../common/moremath.h"
|
||||
#include "../common/guilds.h"
|
||||
#include "../common/MiscFunctions.h"
|
||||
#include "guild_mgr.h"
|
||||
#include "StringIDs.h"
|
||||
#include "NpcAI.h"
|
||||
|
||||
extern WorldServer worldserver;
|
||||
|
||||
void Client::SendGuildMOTD(bool GetGuildMOTDReply) {
|
||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_GuildMOTD, sizeof(GuildMOTD_Struct));
|
||||
|
||||
// When the Client gets an OP_GuildMOTD, it compares the text to the version it has previously stored.
|
||||
// If the text in the OP_GuildMOTD packet is the same, it does nothing. If not the same, it displays
|
||||
// the new MOTD and then stores the new text.
|
||||
//
|
||||
// When the Client receives an OP_GetGuildMOTDReply, it displays the text in the packet.
|
||||
//
|
||||
// So OP_GuildMOTD should be sent on zone entry and when an Officer changes the MOTD, and OP_GetGuildMOTDReply
|
||||
// should be sent when the client issues the /getguildmotd command.
|
||||
//
|
||||
if(GetGuildMOTDReply)
|
||||
outapp->SetOpcode(OP_GetGuildMOTDReply);
|
||||
|
||||
GuildMOTD_Struct *motd = (GuildMOTD_Struct *) outapp->pBuffer;
|
||||
motd->unknown0 = 0;
|
||||
strn0cpy(motd->name, m_pp.name, 64);
|
||||
|
||||
if(IsInAGuild()) {
|
||||
if(!guild_mgr.GetGuildMOTD(GuildID(), motd->motd, motd->setby_name)) {
|
||||
motd->setby_name[0] = '\0';
|
||||
strcpy(motd->motd, "ERROR GETTING MOTD!");
|
||||
}
|
||||
} else {
|
||||
//we have to send them an empty MOTD anywyas.
|
||||
motd->motd[0] = '\0'; //just to be sure
|
||||
motd->setby_name[0] = '\0'; //just to be sure
|
||||
|
||||
}
|
||||
|
||||
mlog(GUILDS__OUT_PACKETS, "Sending OP_GuildMOTD of length %d", outapp->size);
|
||||
mpkt(GUILDS__OUT_PACKET_TRACE, outapp);
|
||||
|
||||
FastQueuePacket(&outapp);
|
||||
}
|
||||
|
||||
void Client::SendGuildURL()
|
||||
{
|
||||
if(GetClientVersion() < EQClientSoF)
|
||||
return;
|
||||
|
||||
if(IsInAGuild())
|
||||
{
|
||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_GuildUpdateURLAndChannel, sizeof(GuildUpdateURLAndChannel_Struct));
|
||||
|
||||
GuildUpdateURLAndChannel_Struct *guuacs = (GuildUpdateURLAndChannel_Struct*) outapp->pBuffer;
|
||||
|
||||
if(guild_mgr.GetGuildURL(GuildID(), guuacs->Text))
|
||||
{
|
||||
guuacs->Action = 0;
|
||||
FastQueuePacket(&outapp);
|
||||
}
|
||||
else
|
||||
safe_delete(outapp);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::SendGuildChannel()
|
||||
{
|
||||
if(GetClientVersion() < EQClientSoF)
|
||||
return;
|
||||
|
||||
if(IsInAGuild())
|
||||
{
|
||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_GuildUpdateURLAndChannel, sizeof(GuildUpdateURLAndChannel_Struct));
|
||||
|
||||
GuildUpdateURLAndChannel_Struct *guuacs = (GuildUpdateURLAndChannel_Struct*) outapp->pBuffer;
|
||||
|
||||
if(guild_mgr.GetGuildChannel(GuildID(), guuacs->Text))
|
||||
{
|
||||
guuacs->Action = 1;
|
||||
|
||||
FastQueuePacket(&outapp);
|
||||
}
|
||||
else
|
||||
safe_delete(outapp);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::SendGuildSpawnAppearance() {
|
||||
if (!IsInAGuild()) {
|
||||
// clear guildtag
|
||||
SendAppearancePacket(AT_GuildID, GUILD_NONE);
|
||||
mlog(GUILDS__OUT_PACKETS, "Sending spawn appearance for no guild tag.");
|
||||
} else {
|
||||
uint8 rank = guild_mgr.GetDisplayedRank(GuildID(), GuildRank(), CharacterID());
|
||||
mlog(GUILDS__OUT_PACKETS, "Sending spawn appearance for guild %d at rank %d", GuildID(), rank);
|
||||
SendAppearancePacket(AT_GuildID, GuildID());
|
||||
SendAppearancePacket(AT_GuildRank, rank);
|
||||
}
|
||||
|
||||
UpdateWho();
|
||||
}
|
||||
|
||||
void Client::SendGuildList() {
|
||||
EQApplicationPacket *outapp;
|
||||
// outapp = new EQApplicationPacket(OP_ZoneGuildList);
|
||||
outapp = new EQApplicationPacket(OP_GuildsList);
|
||||
|
||||
//ask the guild manager to build us a nice guild list packet
|
||||
outapp->pBuffer = guild_mgr.MakeGuildList(/*GetName()*/"", outapp->size);
|
||||
if(outapp->pBuffer == NULL) {
|
||||
mlog(GUILDS__ERROR, "Unable to make guild list!");
|
||||
return;
|
||||
}
|
||||
|
||||
mlog(GUILDS__OUT_PACKETS, "Sending OP_ZoneGuildList of length %d", outapp->size);
|
||||
// mpkt(GUILDS__OUT_PACKET_TRACE, outapp);
|
||||
|
||||
FastQueuePacket(&outapp);
|
||||
}
|
||||
|
||||
|
||||
void Client::SendGuildMembers() {
|
||||
uint32 len;
|
||||
uint8 *data = guild_mgr.MakeGuildMembers(GuildID(), GetName(), len);
|
||||
if(data == NULL)
|
||||
return; //invalid guild, shouldent happen.
|
||||
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_GuildMemberList);
|
||||
outapp->size = len;
|
||||
outapp->pBuffer = data;
|
||||
data = NULL;
|
||||
|
||||
mlog(GUILDS__OUT_PACKETS, "Sending OP_GuildMemberList of length %d", outapp->size);
|
||||
mpkt(GUILDS__OUT_PACKET_TRACE, outapp);
|
||||
|
||||
FastQueuePacket(&outapp);
|
||||
|
||||
ServerPacket* pack = new ServerPacket(ServerOP_RequestOnlineGuildMembers, sizeof(ServerRequestOnlineGuildMembers_Struct));
|
||||
|
||||
ServerRequestOnlineGuildMembers_Struct *srogms = (ServerRequestOnlineGuildMembers_Struct*)pack->pBuffer;
|
||||
|
||||
srogms->FromID = CharacterID();
|
||||
srogms->GuildID = GuildID();
|
||||
|
||||
worldserver.SendPacket(pack);
|
||||
|
||||
safe_delete(pack);
|
||||
|
||||
// We need to send the Guild URL and Channel name again, as sending OP_GuildMemberList appears to clear this information out.
|
||||
SendGuildURL();
|
||||
SendGuildChannel();
|
||||
}
|
||||
|
||||
void Client::RefreshGuildInfo()
|
||||
{
|
||||
uint32 OldGuildID = guild_id;
|
||||
|
||||
guildrank = GUILD_RANK_NONE;
|
||||
guild_id = GUILD_NONE;
|
||||
|
||||
bool WasBanker = GuildBanker;
|
||||
|
||||
CharGuildInfo info;
|
||||
if(!guild_mgr.GetCharInfo(CharacterID(), info)) {
|
||||
mlog(GUILDS__ERROR, "Unable to obtain guild char info for %s (%d)", GetName(), CharacterID());
|
||||
return;
|
||||
}
|
||||
|
||||
guildrank = info.rank;
|
||||
guild_id = info.guild_id;
|
||||
GuildBanker = info.banker || guild_mgr.IsGuildLeader(GuildID(), CharacterID());
|
||||
|
||||
if(((int)zone->GetZoneID() == RuleI(World, GuildBankZoneID)))
|
||||
{
|
||||
if(WasBanker != GuildBanker)
|
||||
{
|
||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_SetGuildRank, sizeof(GuildSetRank_Struct));
|
||||
|
||||
GuildSetRank_Struct *gsrs = (GuildSetRank_Struct*)outapp->pBuffer;
|
||||
|
||||
gsrs->Rank = guildrank;
|
||||
strn0cpy(gsrs->MemberName, GetName(), sizeof(gsrs->MemberName));
|
||||
gsrs->Banker = GuildBanker;
|
||||
|
||||
FastQueuePacket(&outapp);
|
||||
}
|
||||
|
||||
if((guild_id != OldGuildID) && GuildBanks)
|
||||
{
|
||||
ClearGuildBank();
|
||||
|
||||
if(guild_id != GUILD_NONE)
|
||||
GuildBanks->SendGuildBank(this);
|
||||
}
|
||||
}
|
||||
|
||||
SendGuildSpawnAppearance();
|
||||
}
|
||||
|
||||
void EntityList::SendGuildMOTD(uint32 guild_id) {
|
||||
if(guild_id == GUILD_NONE)
|
||||
return;
|
||||
LinkedListIterator<Client*> iterator(client_list);
|
||||
iterator.Reset();
|
||||
while(iterator.MoreElements()) {
|
||||
Client* client = iterator.GetData();
|
||||
if (client->GuildID() == guild_id) {
|
||||
client->SendGuildMOTD();
|
||||
client->SendGuildURL();
|
||||
client->SendGuildChannel();
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
}
|
||||
|
||||
void EntityList::SendGuildSpawnAppearance(uint32 guild_id) {
|
||||
if(guild_id == GUILD_NONE)
|
||||
return;
|
||||
LinkedListIterator<Client*> iterator(client_list);
|
||||
iterator.Reset();
|
||||
while(iterator.MoreElements()) {
|
||||
Client* client = iterator.GetData();
|
||||
if (client->GuildID() == guild_id) {
|
||||
client->SendGuildSpawnAppearance();
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
}
|
||||
|
||||
void EntityList::RefreshAllGuildInfo(uint32 guild_id) {
|
||||
if(guild_id == GUILD_NONE)
|
||||
return;
|
||||
LinkedListIterator<Client*> iterator(client_list);
|
||||
iterator.Reset();
|
||||
while(iterator.MoreElements()) {
|
||||
Client* client = iterator.GetData();
|
||||
if (client->GuildID() == guild_id) {
|
||||
client->RefreshGuildInfo();
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
}
|
||||
|
||||
void EntityList::SendGuildMembers(uint32 guild_id) {
|
||||
if(guild_id == GUILD_NONE)
|
||||
return;
|
||||
|
||||
//this could be optimized a bit to only build the member's packet once
|
||||
//and then keep swapping out the name in the packet on each send.
|
||||
|
||||
LinkedListIterator<Client*> iterator(client_list);
|
||||
iterator.Reset();
|
||||
while(iterator.MoreElements()) {
|
||||
Client* client = iterator.GetData();
|
||||
if (client->GuildID() == guild_id) {
|
||||
client->SendGuildMembers();
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
}
|
||||
|
||||
void EntityList::SendGuildList() {
|
||||
LinkedListIterator<Client*> iterator(client_list);
|
||||
iterator.Reset();
|
||||
while(iterator.MoreElements()) {
|
||||
Client* client = iterator.GetData();
|
||||
client->SendGuildList();
|
||||
iterator.Advance();
|
||||
}
|
||||
}
|
||||
|
||||
void Client::SendGuildJoin(GuildJoin_Struct* gj){
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_GuildManageAdd, sizeof(GuildJoin_Struct));
|
||||
GuildJoin_Struct* outgj=(GuildJoin_Struct*)outapp->pBuffer;
|
||||
outgj->class_ = gj->class_;
|
||||
outgj->guild_id = gj->guild_id;
|
||||
outgj->level = gj->level;
|
||||
strcpy(outgj->name, gj->name);
|
||||
outgj->rank = gj->rank;
|
||||
outgj->zoneid = gj->zoneid;
|
||||
|
||||
mlog(GUILDS__OUT_PACKETS, "Sending OP_GuildManageAdd for join of length %d", outapp->size);
|
||||
mpkt(GUILDS__OUT_PACKET_TRACE, outapp);
|
||||
|
||||
FastQueuePacket(&outapp);
|
||||
|
||||
// SendGuildMembers(gj->guild_id, true);
|
||||
}
|
||||
|
||||
/*
|
||||
void EntityList::SendGuildJoin(GuildJoin_Struct* gj){
|
||||
LinkedListIterator<Client*> iterator(client_list);
|
||||
|
||||
iterator.Reset();
|
||||
while(iterator.MoreElements())
|
||||
{
|
||||
Client* client = iterator.GetData()->CastToClient();
|
||||
if (client->IsInGuild(gj->guild_id))
|
||||
client->SendGuildJoin(gj);
|
||||
iterator.Advance();
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
/*bool Client::SetGuild(uint32 in_guild_id, uint8 in_rank) {
|
||||
if (in_guild_id == 0) {
|
||||
// update DB
|
||||
if (!guild_mgr.SetGuild(character_id, 0, GUILD_MEMBER))
|
||||
return false;
|
||||
// clear guildtag
|
||||
guild_id = GUILD_NONE;
|
||||
SendAppearancePacket(AT_GuildID, GUILD_NONE);
|
||||
SendAppearancePacket(AT_GuildRank, GUILD_RANK_NONE);
|
||||
UpdateWho();
|
||||
return true;
|
||||
} else {
|
||||
if (!guild_mgr.SetGuild(character_id, in_guild_id, in_rank))
|
||||
return false;
|
||||
guildrank = in_rank;
|
||||
if (guild_id != in_guild_id) {
|
||||
guild_id = in_guild_id;
|
||||
SendAppearancePacket(AT_GuildID, in_guild_id);
|
||||
}
|
||||
SendAppearancePacket(AT_GuildRank, in_rank);
|
||||
UpdateWho();
|
||||
return true;
|
||||
}
|
||||
UpdateWho();
|
||||
return false;
|
||||
}*/
|
||||
|
||||
/*
|
||||
void Client::GuildChangeRank(uint32 guild_id, uint32 oldrank, uint32 newrank){
|
||||
GuildChangeRank(GetName(), guild_id, oldrank, newrank);
|
||||
}
|
||||
|
||||
void Client::GuildChangeRank(const char* name, uint32 guild_id, uint32 oldrank, uint32 newrank) {
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_GuildManageStatus, sizeof(GuildManageStatus_Struct));
|
||||
GuildManageStatus_Struct* gms = (GuildManageStatus_Struct*) outapp->pBuffer;
|
||||
gms->guild_id = guild_id;
|
||||
strcpy(gms->name, name);
|
||||
gms->newrank = newrank;
|
||||
gms->oldrank = oldrank;
|
||||
entity_list.QueueClientsGuild(this, outapp, false, guild_id);
|
||||
safe_delete(outapp);
|
||||
SendGuildMembers(guild_id, true);
|
||||
}*/
|
||||
|
||||
|
||||
bool ZoneDatabase::CheckGuildDoor(uint8 doorid,uint16 guild_id,const char* zone) {
|
||||
MYSQL_ROW row;
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
if (!RunQuery(query, MakeAnyLenString(&query,
|
||||
"SELECT guild FROM doors where doorid=%i AND zone='%s'",
|
||||
doorid-128, zone), errbuf, &result))
|
||||
{
|
||||
LogFile->write(EQEMuLog::Error, "Error in CheckGuildDoor query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
} else {
|
||||
if (mysql_num_rows(result) == 1) {
|
||||
row = mysql_fetch_row(result);
|
||||
if (atoi(row[0]) == guild_id)
|
||||
{
|
||||
mysql_free_result(result);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mysql_free_result(result);
|
||||
return false;
|
||||
}
|
||||
|
||||
// code below will never be reached
|
||||
mysql_free_result(result);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ZoneDatabase::SetGuildDoor(uint8 doorid,uint16 guild_id, const char* zone) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
uint32 affected_rows = 0;
|
||||
if (doorid > 127)
|
||||
doorid = doorid - 128;
|
||||
if (!RunQuery(query, MakeAnyLenString(&query,
|
||||
"UPDATE doors SET guild = %i WHERE (doorid=%i) AND (zone='%s')",
|
||||
guild_id, doorid, zone), errbuf, 0,&affected_rows))
|
||||
{
|
||||
LogFile->write(EQEMuLog::Error, "Error in SetGuildDoor query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
|
||||
safe_delete_array(query);
|
||||
|
||||
return(affected_rows > 0);
|
||||
}
|
||||
|
||||
+1613
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,144 @@
|
||||
#ifndef GUILD_MGR_H_
|
||||
#define GUILD_MGR_H_
|
||||
|
||||
#include "../common/types.h"
|
||||
#include "../common/guild_base.h"
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include "../zone/petitions.h"
|
||||
|
||||
extern PetitionList petition_list;
|
||||
//extern GuildRanks_Struct guilds[512];
|
||||
//extern ZoneDatabase database;
|
||||
|
||||
#define PBUFFER 50
|
||||
#define MBUFFER 50
|
||||
|
||||
#define GUILD_BANK_MAIN_AREA_SIZE 200
|
||||
#define GUILD_BANK_DEPOSIT_AREA_SIZE 20
|
||||
class Client;
|
||||
class ServerPacket;
|
||||
|
||||
struct GuildBankItem
|
||||
{
|
||||
uint32 ItemID;
|
||||
uint32 Quantity;
|
||||
char Donator[64];
|
||||
uint8 Permissions;
|
||||
char WhoFor[64];
|
||||
};
|
||||
|
||||
struct GuildBankItems
|
||||
{
|
||||
GuildBankItem MainArea[GUILD_BANK_MAIN_AREA_SIZE];
|
||||
GuildBankItem DepositArea[GUILD_BANK_DEPOSIT_AREA_SIZE];
|
||||
};
|
||||
|
||||
struct GuildBank
|
||||
{
|
||||
uint32 GuildID;
|
||||
GuildBankItems Items;
|
||||
};
|
||||
|
||||
enum { GuildBankBulkItems = 0, GuildBankItemUpdate = 1, GuildBankPromote = 3, GuildBankViewItem = 4, GuildBankDeposit = 5,
|
||||
GuildBankPermissions = 6, GuildBankWithdraw = 7, GuildBankSplitStacks = 8, GuildBankMergeStacks = 9, GuildBankAcknowledge = 10 };
|
||||
|
||||
enum { GuildBankDepositArea = 0, GuildBankMainArea = 1 };
|
||||
|
||||
enum { GuildBankBankerOnly = 0, GuildBankSingleMember = 1, GuildBankPublicIfUsable = 2, GuildBankPublic = 3 };
|
||||
|
||||
class GuildApproval
|
||||
{
|
||||
public:
|
||||
GuildApproval(const char* guildname,Client* owner,uint32 id);
|
||||
~GuildApproval();
|
||||
bool ProcessApproval();
|
||||
bool AddMemberApproval(Client* addition);
|
||||
uint32 GetID() { return refid; }
|
||||
Client* GetOwner() { return owner; }
|
||||
void GuildApproved();
|
||||
void ApprovedMembers(Client* requestee);
|
||||
private:
|
||||
Timer* deletion_timer;
|
||||
char guild[16];
|
||||
char founders[3];
|
||||
Client* owner;
|
||||
Client* members[6];
|
||||
uint32 refid;
|
||||
};
|
||||
|
||||
class ZoneGuildManager : public BaseGuildManager {
|
||||
public:
|
||||
~ZoneGuildManager(void);
|
||||
|
||||
void AddGuildApproval(const char* guildname, Client* owner);
|
||||
void AddMemberApproval(uint32 refid,Client* name);
|
||||
void ClearGuildsApproval();
|
||||
GuildApproval* FindGuildByIDApproval(uint32 refid);
|
||||
GuildApproval* FindGuildByOwnerApproval(Client* owner);
|
||||
void ProcessApproval();
|
||||
uint32 GetFreeID() { return id+1; }
|
||||
//called by worldserver when it receives a message from world.
|
||||
void ProcessWorldPacket(ServerPacket *pack);
|
||||
|
||||
void ListGuilds(Client *c) const;
|
||||
void DescribeGuild(Client *c, uint32 guild_id) const;
|
||||
|
||||
|
||||
// bool DonateTribute(uint32 charid, uint32 guild_id, uint32 tribute_amount);
|
||||
|
||||
uint8 *MakeGuildMembers(uint32 guild_id, const char *prefix_name, uint32 &length); //make a guild member list packet, returns ownership of the buffer.
|
||||
|
||||
void RecordInvite(uint32 char_id, uint32 guild_id, uint8 rank);
|
||||
bool VerifyAndClearInvite(uint32 char_id, uint32 guild_id, uint8 rank);
|
||||
void SendGuildMemberUpdateToWorld(const char *MemberName, uint32 GuildID, uint16 ZoneID, uint32 LastSeen);
|
||||
void RequestOnlineGuildMembers(uint32 FromID, uint32 GuildID);
|
||||
|
||||
protected:
|
||||
virtual void SendGuildRefresh(uint32 guild_id, bool name, bool motd, bool rank, bool relation);
|
||||
virtual void SendCharRefresh(uint32 old_guild_id, uint32 guild_id, uint32 charid);
|
||||
virtual void SendRankUpdate(uint32 CharID);
|
||||
virtual void SendGuildDelete(uint32 guild_id);
|
||||
|
||||
std::map<uint32, std::pair<uint32, uint8> > m_inviteQueue; //map from char ID to guild,rank
|
||||
|
||||
private:
|
||||
LinkedList<GuildApproval*> list;
|
||||
uint32 id;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class GuildBankManager
|
||||
{
|
||||
|
||||
public:
|
||||
~GuildBankManager();
|
||||
void SendGuildBank(Client *c);
|
||||
bool AddItem(uint32 GuildID, uint8 Area, uint32 ItemID, int32 QtyOrCharges, const char *Donator, uint8 Permissions, const char *WhoFor);
|
||||
int Promote(uint32 GuildID, int SlotID);
|
||||
void SetPermissions(uint32 GuildID, uint16 SlotID, uint32 Permissions, const char *MemberName);
|
||||
ItemInst* GetItem(uint32 GuildID, uint16 Area, uint16 SlotID, uint32 Quantity);
|
||||
bool DeleteItem(uint32 GuildID, uint16 Area, uint16 SlotID, uint32 Quantity);
|
||||
bool HasItem(uint32 GuildID, uint32 ItemID);
|
||||
bool IsAreaFull(uint32 GuildID, uint16 Area);
|
||||
bool MergeStacks(uint32 GuildID, uint16 SlotID);
|
||||
bool SplitStack(uint32 GuildID, uint16 SlotID, uint32 Quantity);
|
||||
bool AllowedToWithdraw(uint32 GuildID, uint16 Area, uint16 SlotID, const char *Name);
|
||||
|
||||
private:
|
||||
bool IsLoaded(uint32 GuildID);
|
||||
bool Load(uint32 GuildID);
|
||||
std::list<GuildBank*>::iterator GetGuildBank(uint32 GuildID);
|
||||
void UpdateItemQuantity(uint32 GuildID, uint16 Area, uint16 SlotID, uint32 Quantity);
|
||||
|
||||
std::list<GuildBank*> Banks;
|
||||
|
||||
};
|
||||
|
||||
extern ZoneGuildManager guild_mgr;
|
||||
extern GuildBankManager *GuildBanks;
|
||||
|
||||
|
||||
#endif /*GUILD_MGR_H_*/
|
||||
|
||||
@@ -0,0 +1,577 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "../common/debug.h"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "masterentity.h"
|
||||
#include "../common/linked_list.h"
|
||||
#include "../common/rulesys.h"
|
||||
#include "../common/MiscFunctions.h"
|
||||
#include "hate_list.h"
|
||||
#include "QuestParserCollection.h"
|
||||
#include "zone.h"
|
||||
#include "watermap.h"
|
||||
|
||||
extern Zone *zone;
|
||||
|
||||
HateList::HateList()
|
||||
{
|
||||
owner = NULL;
|
||||
}
|
||||
|
||||
HateList::~HateList()
|
||||
{
|
||||
}
|
||||
|
||||
// neotokyo: added for frenzy support
|
||||
// checks if target still is in frenzy mode
|
||||
void HateList::CheckFrenzyHate()
|
||||
{
|
||||
LinkedListIterator<tHateEntry*> iterator(list);
|
||||
iterator.Reset();
|
||||
while(iterator.MoreElements())
|
||||
{
|
||||
if (iterator.GetData()->ent->GetHPRatio() >= 20)
|
||||
iterator.GetData()->bFrenzy = false;
|
||||
iterator.Advance();
|
||||
}
|
||||
}
|
||||
|
||||
void HateList::Wipe()
|
||||
{
|
||||
LinkedListIterator<tHateEntry*> iterator(list);
|
||||
iterator.Reset();
|
||||
|
||||
while(iterator.MoreElements())
|
||||
{
|
||||
Mob* m = iterator.GetData()->ent;
|
||||
parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), m, "0", 0);
|
||||
iterator.RemoveCurrent();
|
||||
|
||||
if(m->IsClient())
|
||||
m->CastToClient()->DecrementAggroCount();
|
||||
}
|
||||
}
|
||||
|
||||
bool HateList::IsOnHateList(Mob *mob)
|
||||
{
|
||||
if (Find(mob))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
tHateEntry *HateList::Find(Mob *ent)
|
||||
{
|
||||
_ZP(HateList_Find);
|
||||
LinkedListIterator<tHateEntry*> iterator(list);
|
||||
iterator.Reset();
|
||||
while(iterator.MoreElements())
|
||||
{
|
||||
if(iterator.GetData()->ent == ent)
|
||||
return iterator.GetData();
|
||||
iterator.Advance();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void HateList::Set(Mob* other, uint32 in_hate, uint32 in_dam)
|
||||
{
|
||||
tHateEntry *p = Find(other);
|
||||
if(p)
|
||||
{
|
||||
if(in_dam > 0)
|
||||
p->damage = in_dam;
|
||||
if(in_hate > 0)
|
||||
p->hate = in_hate;
|
||||
}
|
||||
}
|
||||
|
||||
Mob* HateList::GetDamageTop(Mob* hater)
|
||||
{
|
||||
_ZP(HateList_GetDamageTop);
|
||||
Mob* current = NULL;
|
||||
Group* grp = NULL;
|
||||
Raid* r = NULL;
|
||||
uint32 dmg_amt = 0;
|
||||
|
||||
LinkedListIterator<tHateEntry*> iterator(list);
|
||||
iterator.Reset();
|
||||
while(iterator.MoreElements())
|
||||
{
|
||||
grp = NULL;
|
||||
r = NULL;
|
||||
|
||||
if(iterator.GetData()->ent && iterator.GetData()->ent->IsClient()){
|
||||
r = entity_list.GetRaidByClient(iterator.GetData()->ent->CastToClient());
|
||||
}
|
||||
|
||||
grp = entity_list.GetGroupByMob(iterator.GetData()->ent);
|
||||
|
||||
if(iterator.GetData()->ent && r){
|
||||
if(r->GetTotalRaidDamage(hater) >= dmg_amt)
|
||||
{
|
||||
current = iterator.GetData()->ent;
|
||||
dmg_amt = r->GetTotalRaidDamage(hater);
|
||||
}
|
||||
}
|
||||
else if (iterator.GetData()->ent != NULL && grp != NULL)
|
||||
{
|
||||
if (grp->GetTotalGroupDamage(hater) >= dmg_amt)
|
||||
{
|
||||
current = iterator.GetData()->ent;
|
||||
dmg_amt = grp->GetTotalGroupDamage(hater);
|
||||
}
|
||||
}
|
||||
else if (iterator.GetData()->ent != NULL && (uint32)iterator.GetData()->damage >= dmg_amt)
|
||||
{
|
||||
current = iterator.GetData()->ent;
|
||||
dmg_amt = iterator.GetData()->damage;
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
Mob* HateList::GetClosest(Mob *hater) {
|
||||
_ZP(HateList_GetClosest);
|
||||
Mob* close = NULL;
|
||||
float closedist = 99999.9f;
|
||||
float thisdist;
|
||||
|
||||
LinkedListIterator<tHateEntry*> iterator(list);
|
||||
iterator.Reset();
|
||||
while(iterator.MoreElements()) {
|
||||
thisdist = iterator.GetData()->ent->DistNoRootNoZ(*hater);
|
||||
if(iterator.GetData()->ent != NULL && thisdist <= closedist) {
|
||||
closedist = thisdist;
|
||||
close = iterator.GetData()->ent;
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
|
||||
if (close == 0 && hater->IsNPC())
|
||||
close = hater->CastToNPC()->GetHateTop();
|
||||
|
||||
return close;
|
||||
}
|
||||
|
||||
|
||||
// neotokyo: a few comments added, rearranged code for readability
|
||||
void HateList::Add(Mob *ent, int32 in_hate, int32 in_dam, bool bFrenzy, bool iAddIfNotExist)
|
||||
{
|
||||
if(!ent)
|
||||
return;
|
||||
|
||||
if(ent->IsCorpse())
|
||||
return;
|
||||
|
||||
if(ent->IsClient() && ent->CastToClient()->IsDead())
|
||||
return;
|
||||
|
||||
tHateEntry *p = Find(ent);
|
||||
if (p)
|
||||
{
|
||||
p->damage+=(in_dam>=0)?in_dam:0;
|
||||
p->hate+=in_hate;
|
||||
p->bFrenzy = bFrenzy;
|
||||
}
|
||||
else if (iAddIfNotExist) {
|
||||
p = new tHateEntry;
|
||||
p->ent = ent;
|
||||
p->damage = (in_dam>=0)?in_dam:0;
|
||||
p->hate = in_hate;
|
||||
p->bFrenzy = bFrenzy;
|
||||
list.Append(p);
|
||||
parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), ent, "1", 0);
|
||||
|
||||
if(ent->IsClient())
|
||||
ent->CastToClient()->IncrementAggroCount();
|
||||
}
|
||||
}
|
||||
|
||||
bool HateList::RemoveEnt(Mob *ent)
|
||||
{
|
||||
bool found = false;
|
||||
LinkedListIterator<tHateEntry*> iterator(list);
|
||||
iterator.Reset();
|
||||
|
||||
while(iterator.MoreElements())
|
||||
{
|
||||
if(iterator.GetData()->ent == ent)
|
||||
{
|
||||
parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), ent, "0", 0);
|
||||
iterator.RemoveCurrent();
|
||||
found = true;
|
||||
|
||||
if(ent->IsClient())
|
||||
ent->CastToClient()->DecrementAggroCount();
|
||||
|
||||
}
|
||||
else
|
||||
iterator.Advance();
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
void HateList::DoFactionHits(int32 nfl_id) {
|
||||
_ZP(HateList_DoFactionHits);
|
||||
if (nfl_id <= 0)
|
||||
return;
|
||||
LinkedListIterator<tHateEntry*> iterator(list);
|
||||
iterator.Reset();
|
||||
while(iterator.MoreElements())
|
||||
{
|
||||
Client *p;
|
||||
|
||||
if (iterator.GetData()->ent && iterator.GetData()->ent->IsClient())
|
||||
p = iterator.GetData()->ent->CastToClient();
|
||||
else
|
||||
p = NULL;
|
||||
|
||||
if (p)
|
||||
p->SetFactionLevel(p->CharacterID(), nfl_id, p->GetBaseClass(), p->GetBaseRace(), p->GetDeity());
|
||||
iterator.Advance();
|
||||
}
|
||||
}
|
||||
|
||||
Mob *HateList::GetTop(Mob *center)
|
||||
{
|
||||
_ZP(HateList_GetTop);
|
||||
Mob* top = NULL;
|
||||
int32 hate = -1;
|
||||
|
||||
if (RuleB(Aggro,SmartAggroList)){
|
||||
Mob* topClientInRange = NULL;
|
||||
int32 hateClientInRange = -1;
|
||||
int skipped_count = 0;
|
||||
|
||||
LinkedListIterator<tHateEntry*> iterator(list);
|
||||
iterator.Reset();
|
||||
while(iterator.MoreElements())
|
||||
{
|
||||
tHateEntry *cur = iterator.GetData();
|
||||
int16 aggroMod = 0;
|
||||
|
||||
if(!cur){
|
||||
iterator.Advance();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!cur->ent){
|
||||
iterator.Advance();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
|
||||
if(!zone->watermap->InLiquid(cur->ent->GetX(), cur->ent->GetY(), cur->ent->GetZ())) {
|
||||
skipped_count++;
|
||||
iterator.Advance();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(cur->ent->DivineAura() || cur->ent->IsMezzed() || cur->ent->IsFeared()){
|
||||
if(hate == -1)
|
||||
{
|
||||
top = cur->ent;
|
||||
hate = 0;
|
||||
}
|
||||
iterator.Advance();
|
||||
continue;
|
||||
}
|
||||
|
||||
int32 currentHate = cur->hate;
|
||||
|
||||
if(cur->ent->IsClient()){
|
||||
|
||||
if(cur->ent->CastToClient()->IsSitting()){
|
||||
aggroMod += RuleI(Aggro, SittingAggroMod);
|
||||
}
|
||||
|
||||
if(center){
|
||||
if(center->GetTarget() == cur->ent)
|
||||
aggroMod += RuleI(Aggro, CurrentTargetAggroMod);
|
||||
if(RuleI(Aggro, MeleeRangeAggroMod) != 0)
|
||||
{
|
||||
if(center->CombatRange(cur->ent)){
|
||||
aggroMod += RuleI(Aggro, MeleeRangeAggroMod);
|
||||
|
||||
if(currentHate > hateClientInRange || cur->bFrenzy){
|
||||
hateClientInRange = currentHate;
|
||||
topClientInRange = cur->ent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else{
|
||||
if(center){
|
||||
if(center->GetTarget() == cur->ent)
|
||||
aggroMod += RuleI(Aggro, CurrentTargetAggroMod);
|
||||
if(RuleI(Aggro, MeleeRangeAggroMod) != 0)
|
||||
{
|
||||
if(center->CombatRange(cur->ent)){
|
||||
aggroMod += RuleI(Aggro, MeleeRangeAggroMod);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(cur->ent->GetMaxHP() != 0 && ((cur->ent->GetHP()*100/cur->ent->GetMaxHP()) < 20)){
|
||||
aggroMod += RuleI(Aggro, CriticallyWoundedAggroMod);
|
||||
}
|
||||
|
||||
if(aggroMod){
|
||||
currentHate += (currentHate * aggroMod / 100);
|
||||
}
|
||||
|
||||
if(currentHate > hate || cur->bFrenzy){
|
||||
hate = currentHate;
|
||||
top = cur->ent;
|
||||
}
|
||||
|
||||
iterator.Advance();
|
||||
}
|
||||
|
||||
if(topClientInRange != NULL && top != NULL) {
|
||||
bool isTopClientType = top->IsClient();
|
||||
#ifdef BOTS
|
||||
if(!isTopClientType) {
|
||||
if(top->IsBot()) {
|
||||
isTopClientType = true;
|
||||
topClientInRange = top;
|
||||
}
|
||||
}
|
||||
#endif //BOTS
|
||||
if(!isTopClientType)
|
||||
return topClientInRange;
|
||||
|
||||
return top;
|
||||
}
|
||||
else {
|
||||
if(top == NULL && skipped_count > 0) {
|
||||
return center->GetTarget();
|
||||
}
|
||||
return top;
|
||||
}
|
||||
}
|
||||
else{
|
||||
LinkedListIterator<tHateEntry*> iterator(list);
|
||||
iterator.Reset();
|
||||
int skipped_count = 0;
|
||||
while(iterator.MoreElements())
|
||||
{
|
||||
tHateEntry *cur = iterator.GetData();
|
||||
if(center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
|
||||
if(!zone->watermap->InLiquid(cur->ent->GetX(), cur->ent->GetY(), cur->ent->GetZ())) {
|
||||
skipped_count++;
|
||||
iterator.Advance();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(cur->ent != NULL && ((cur->hate > hate) || cur->bFrenzy ))
|
||||
{
|
||||
top = cur->ent;
|
||||
hate = cur->hate;
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
if(top == NULL && skipped_count > 0) {
|
||||
return center->GetTarget();
|
||||
}
|
||||
return top;
|
||||
}
|
||||
}
|
||||
|
||||
Mob *HateList::GetMostHate(){
|
||||
_ZP(HateList_GetMostHate);
|
||||
|
||||
Mob* top = NULL;
|
||||
int32 hate = -1;
|
||||
|
||||
LinkedListIterator<tHateEntry*> iterator(list);
|
||||
iterator.Reset();
|
||||
while(iterator.MoreElements())
|
||||
{
|
||||
tHateEntry *cur = iterator.GetData();
|
||||
if(cur->ent != NULL && (cur->hate > hate))
|
||||
{
|
||||
top = cur->ent;
|
||||
hate = cur->hate;
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
return top;
|
||||
}
|
||||
|
||||
|
||||
Mob *HateList::GetRandom()
|
||||
{
|
||||
int count = 0;
|
||||
LinkedListIterator<tHateEntry*> iterator(list);
|
||||
iterator.Reset();
|
||||
while(iterator.MoreElements())
|
||||
{
|
||||
iterator.Advance();
|
||||
count++;
|
||||
}
|
||||
if(!count)
|
||||
return NULL;
|
||||
|
||||
int random = MakeRandomInt(0, count-1);
|
||||
iterator.Reset();
|
||||
for (int i = 0; i < random-1; i++)
|
||||
iterator.Advance();
|
||||
return iterator.GetData()->ent;
|
||||
}
|
||||
|
||||
int32 HateList::GetEntHate(Mob *ent, bool damage)
|
||||
{
|
||||
tHateEntry *p;
|
||||
|
||||
p = Find(ent);
|
||||
|
||||
if ( p && damage)
|
||||
return p->damage;
|
||||
else if (p)
|
||||
return p->hate;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
//looking for any mob with hate > -1
|
||||
bool HateList::IsEmpty() {
|
||||
_ZP(HateList_IsEmpty);
|
||||
|
||||
return(list.Count() == 0);
|
||||
}
|
||||
|
||||
// Prints hate list to a client
|
||||
void HateList::PrintToClient(Client *c)
|
||||
{
|
||||
LinkedListIterator<tHateEntry*> iterator(list);
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements())
|
||||
{
|
||||
tHateEntry *e = iterator.GetData();
|
||||
c->Message(0, "- name: %s, damage: %d, hate: %d",
|
||||
(e->ent && e->ent->GetName()) ? e->ent->GetName() : "(null)",
|
||||
e->damage, e->hate);
|
||||
|
||||
iterator.Advance();
|
||||
}
|
||||
}
|
||||
|
||||
int HateList::AreaRampage(Mob *caster, Mob *target)
|
||||
{
|
||||
if(!target || !caster)
|
||||
return 0;
|
||||
|
||||
int ret = 0;
|
||||
std::list<uint32> id_list;
|
||||
LinkedListIterator<tHateEntry*> iterator(list);
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements())
|
||||
{
|
||||
tHateEntry *h = iterator.GetData();
|
||||
iterator.Advance();
|
||||
if(h && h->ent && h->ent != caster)
|
||||
{
|
||||
if(caster->CombatRange(h->ent))
|
||||
{
|
||||
id_list.push_back(h->ent->GetID());
|
||||
++ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::list<uint32>::iterator iter = id_list.begin();
|
||||
while(iter != id_list.end())
|
||||
{
|
||||
Mob *cur = entity_list.GetMobID((*iter));
|
||||
if(cur)
|
||||
{
|
||||
caster->Attack(cur);
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void HateList::SpellCast(Mob *caster, uint32 spell_id, float range)
|
||||
{
|
||||
if(!caster)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//this is slower than just iterating through the list but avoids
|
||||
//crashes when people kick the bucket in the middle of this call
|
||||
//that invalidates our iterator but there's no way to know sadly
|
||||
//So keep a list of entity ids and look up after
|
||||
std::list<uint32> id_list;
|
||||
range = range * range;
|
||||
LinkedListIterator<tHateEntry*> iterator(list);
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements())
|
||||
{
|
||||
tHateEntry *h = iterator.GetData();
|
||||
if(range > 0)
|
||||
{
|
||||
if(caster->DistNoRoot(*h->ent) <= range)
|
||||
{
|
||||
id_list.push_back(h->ent->GetID());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
id_list.push_back(h->ent->GetID());
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
|
||||
std::list<uint32>::iterator iter = id_list.begin();
|
||||
while(iter != id_list.end())
|
||||
{
|
||||
Mob *cur = entity_list.GetMobID((*iter));
|
||||
if(cur)
|
||||
{
|
||||
caster->SpellOnTarget(spell_id, cur);
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HateList::GetHateList(std::list<tHateEntry*> &h_list)
|
||||
{
|
||||
h_list.clear();
|
||||
LinkedListIterator<tHateEntry*> iterator(list);
|
||||
iterator.Reset();
|
||||
while(iterator.MoreElements())
|
||||
{
|
||||
tHateEntry *ent = iterator.GetData();
|
||||
h_list.push_back(ent);
|
||||
iterator.Advance();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef HATELIST_H
|
||||
#define HATELIST_H
|
||||
|
||||
class tHateEntry
|
||||
{
|
||||
public:
|
||||
Mob *ent;
|
||||
int32 damage, hate;
|
||||
bool bFrenzy;
|
||||
};
|
||||
|
||||
class HateList
|
||||
{
|
||||
public:
|
||||
HateList();
|
||||
~HateList();
|
||||
|
||||
// adds a mob to the hatelist
|
||||
void Add(Mob *ent, int32 in_hate=0, int32 in_dam=0, bool bFrenzy = false, bool iAddIfNotExist = true);
|
||||
// sets existing hate
|
||||
void Set(Mob *other, uint32 in_hate, uint32 in_dam);
|
||||
// removes mobs from hatelist
|
||||
bool RemoveEnt(Mob *ent);
|
||||
// Remove all
|
||||
void Wipe();
|
||||
// ???
|
||||
void DoFactionHits(int32 nfl_id);
|
||||
// Gets Hate amount for mob
|
||||
int32 GetEntHate(Mob *ent, bool damage = false);
|
||||
// gets top hated mob
|
||||
Mob *GetTop(Mob *center);
|
||||
// gets any on the list
|
||||
Mob *GetRandom();
|
||||
// get closest mob or NULL if list empty
|
||||
Mob *GetClosest(Mob *hater);
|
||||
// gets top mob or NULL if hate list empty
|
||||
Mob *GetDamageTop(Mob *hater);
|
||||
// used to check if mob is on hatelist
|
||||
bool IsOnHateList(Mob *);
|
||||
// used to remove or add frenzy hate
|
||||
void CheckFrenzyHate();
|
||||
//Gets the target with the most hate regardless of things like frenzy etc.
|
||||
Mob* GetMostHate();
|
||||
|
||||
int AreaRampage(Mob *caster, Mob *target);
|
||||
|
||||
void SpellCast(Mob *caster, uint32 spell_id, float range);
|
||||
|
||||
bool IsEmpty();
|
||||
void PrintToClient(Client *c);
|
||||
|
||||
//For accessing the hate list via perl; don't use for anything else
|
||||
void GetHateList(std::list<tHateEntry*> &h_list);
|
||||
|
||||
//setting owner
|
||||
void SetOwner(Mob *newOwner) { owner = newOwner; }
|
||||
|
||||
protected:
|
||||
tHateEntry *Find(Mob *ent);
|
||||
private:
|
||||
LinkedList<tHateEntry*> list;
|
||||
Mob *owner;
|
||||
};
|
||||
|
||||
#endif
|
||||
+208
@@ -0,0 +1,208 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "../common/debug.h"
|
||||
#include "masterentity.h"
|
||||
#include "../common/Item.h"
|
||||
#include "../common/linked_list.h"
|
||||
#include "../common/MiscFunctions.h"
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include "worldserver.h"
|
||||
|
||||
map<uint16, const NPCType *> Horse::horse_types;
|
||||
LinkedList<NPCType *> horses_auto_delete;
|
||||
|
||||
Horse::Horse(Client *_owner, uint16 spell_id, float x, float y, float z, float heading)
|
||||
: NPC(GetHorseType(spell_id), NULL, x, y, z, heading, FlyMode3)
|
||||
{
|
||||
//give the horse its proper name.
|
||||
strn0cpy(name, _owner->GetCleanName(), 55);
|
||||
strcat(name,"`s_Mount00");
|
||||
|
||||
owner = _owner;
|
||||
}
|
||||
|
||||
void Horse::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
|
||||
NPC::FillSpawnStruct(ns, ForWho);
|
||||
|
||||
// ns->spawn.texture = NPCTypedata->mount_color;
|
||||
ns->spawn.petOwnerId = 0;
|
||||
|
||||
//dunno why we do these, they should allready be set right.
|
||||
ns->spawn.runspeed = NPCTypedata->runspeed;
|
||||
}
|
||||
|
||||
bool Horse::IsHorseSpell(uint16 spell_id) {
|
||||
//written in terms of a function which does a ton more work
|
||||
//than we need to to figure out if this is a horse spell.
|
||||
//the logic is that people calling this function will post
|
||||
//likely immediately summon the horse, so we need the extra anyways.
|
||||
return(GetHorseType(spell_id) != NULL);
|
||||
}
|
||||
|
||||
const NPCType *Horse::GetHorseType(uint16 spell_id) {
|
||||
if(horse_types.count(spell_id) == 1)
|
||||
return(horse_types[spell_id]);
|
||||
//cache invalid spell IDs as NULL entries
|
||||
const NPCType *ret;
|
||||
horse_types[spell_id] = ret = BuildHorseType(spell_id);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
const NPCType *Horse::BuildHorseType(uint16 spell_id) {
|
||||
|
||||
const char* FileName = spells[spell_id].teleport_zone;
|
||||
|
||||
char mount_color = 0;
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (database.RunQuery(query,MakeAnyLenString(&query, "SELECT race,gender,texture,mountspeed FROM horses WHERE filename='%s'", FileName), errbuf, &result)) {
|
||||
|
||||
safe_delete_array(query);
|
||||
if (mysql_num_rows(result) == 1) {
|
||||
|
||||
row = mysql_fetch_row(result);
|
||||
|
||||
NPCType* npc_type = new NPCType;
|
||||
memset(npc_type, 0, sizeof(NPCType));
|
||||
strcpy(npc_type->name,"Unclaimed_Mount"); //this should never get used
|
||||
strcpy(npc_type->npc_attacks,"ABH");
|
||||
npc_type->cur_hp = 1;
|
||||
npc_type->max_hp = 1;
|
||||
npc_type->race = atoi(row[0]);
|
||||
npc_type->gender = atoi(row[1]); // Drogmor's are female horses. Yuck.
|
||||
npc_type->class_ = 1;
|
||||
npc_type->deity= 1;
|
||||
npc_type->level = 1;
|
||||
npc_type->npc_id = 0;
|
||||
npc_type->loottable_id = 0;
|
||||
npc_type->texture = atoi(row[2]);
|
||||
npc_type->helmtexture = atoi(row[2]);
|
||||
npc_type->runspeed = atof(row[3]);
|
||||
|
||||
mount_color = atoi(row[2]);
|
||||
|
||||
npc_type->light = 0;
|
||||
npc_type->STR = 75;
|
||||
npc_type->STA = 75;
|
||||
npc_type->DEX = 75;
|
||||
npc_type->AGI = 75;
|
||||
npc_type->INT = 75;
|
||||
npc_type->WIS = 75;
|
||||
npc_type->CHA = 75;
|
||||
|
||||
horses_auto_delete.Insert(npc_type);
|
||||
|
||||
mysql_free_result(result);
|
||||
return(npc_type);
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "No Database entry for mount: %s, check the horses table", FileName);
|
||||
//Message(13, "Unable to find data for mount %s", FileName);
|
||||
safe_delete_array(query);
|
||||
}
|
||||
mysql_free_result(result);
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in Mount query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Client::SummonHorse(uint16 spell_id) {
|
||||
if (GetHorseId() != 0) {
|
||||
Message(13,"You already have a Horse. Get off, Fatbutt!");
|
||||
return;
|
||||
}
|
||||
if(!Horse::IsHorseSpell(spell_id)) {
|
||||
LogFile->write(EQEMuLog::Error, "%s tried to summon an unknown horse, spell id %d", GetName(), spell_id);
|
||||
return;
|
||||
}
|
||||
|
||||
// No Horse, lets get them one.
|
||||
|
||||
Horse* horse = new Horse(this, spell_id, GetX(), GetY(), GetZ(), GetHeading());
|
||||
|
||||
//we want to manage the spawn packet ourself.
|
||||
//another reason is we dont want quests executing on it.
|
||||
entity_list.AddNPC(horse, false);
|
||||
|
||||
// Okay, lets say they have a horse now.
|
||||
|
||||
|
||||
EQApplicationPacket outapp;
|
||||
horse->CreateHorseSpawnPacket(&outapp, GetName(), GetID());
|
||||
/* // Doodman: Kludged in here instead of adding a field to PCType. FIXME!
|
||||
NewSpawn_Struct* ns=(NewSpawn_Struct*)outapp->pBuffer;
|
||||
ns->spawn.texture=mount_color;
|
||||
ns->spawn.pet_owner_id=0;
|
||||
ns->spawn.walkspeed=npc_type->walkspeed;
|
||||
ns->spawn.runspeed=npc_type->runspeed;
|
||||
*/
|
||||
entity_list.QueueClients(horse, &outapp);
|
||||
|
||||
|
||||
uint16 tmpID = horse->GetID();
|
||||
SetHorseId(tmpID);
|
||||
|
||||
}
|
||||
|
||||
void Client::SetHorseId(uint16 horseid_in) {
|
||||
//if its the same, do nothing
|
||||
if(horseId == horseid_in)
|
||||
return;
|
||||
|
||||
//otherwise it changed.
|
||||
//if we have a horse, get rid of it no matter what.
|
||||
if(horseId) {
|
||||
Mob *horse = entity_list.GetMob(horseId);
|
||||
if(horse != NULL)
|
||||
horse->Depop();
|
||||
}
|
||||
|
||||
//now we take whatever they gave us.
|
||||
horseId = horseid_in;
|
||||
}
|
||||
|
||||
void Mob::CreateHorseSpawnPacket(EQApplicationPacket* app, const char* ownername, uint16 ownerid, Mob* ForWho) {
|
||||
app->SetOpcode(OP_NewSpawn);
|
||||
app->pBuffer = new uchar[sizeof(NewSpawn_Struct)];
|
||||
app->size = sizeof(NewSpawn_Struct);
|
||||
memset(app->pBuffer, 0, sizeof(NewSpawn_Struct));
|
||||
NewSpawn_Struct* ns = (NewSpawn_Struct*)app->pBuffer;
|
||||
FillSpawnStruct(ns, ForWho);
|
||||
|
||||
#if (EQDEBUG >= 11)
|
||||
printf("Horse Spawn Packet - Owner: %s\n", ownername);
|
||||
DumpPacket(app);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef HORSES_H
|
||||
#define HORSES_H
|
||||
|
||||
|
||||
#include "../common/debug.h"
|
||||
#include "npc.h"
|
||||
|
||||
#include <map>
|
||||
using namespace std;
|
||||
|
||||
class Horse : public NPC {
|
||||
public:
|
||||
Horse(Client *owner, uint16 spell_id, float x, float y, float z, float heading);
|
||||
|
||||
virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
|
||||
|
||||
static bool IsHorseSpell(uint16 spell_id);
|
||||
protected:
|
||||
uint8 mount_color;
|
||||
Client *owner;
|
||||
|
||||
//generate npc type records for horses
|
||||
static map<uint16, const NPCType *> horse_types;
|
||||
static const NPCType *GetHorseType(uint16 spell_id);
|
||||
static const NPCType *BuildHorseType(uint16 spell_id);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
+2398
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,81 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
alter table npc_types add column loottable_id int(11) unsigned not null;
|
||||
|
||||
create table loottable (id int(11) unsigned auto_increment primary key, name varchar(255) not null unique,
|
||||
mincash int(11) unsigned not null, maxcash int(11) unsigned not null, avgcoin smallint(4) unsigned not null default 0);
|
||||
|
||||
create table loottable_entries (loottable_id int(11) unsigned not null, lootdrop_id int(11) unsigned not null,
|
||||
multiplier tinyint(2) unsigned default 1 not null, probability tinyint(2) unsigned default 100 not null,
|
||||
primary key (loottable_id, lootdrop_id));
|
||||
|
||||
create table lootdrop (id int(11) unsigned auto_increment primary key, name varchar(255) not null unique);
|
||||
|
||||
create table lootdrop_entries (lootdrop_id int(11) unsigned not null, item_id int(11) not null,
|
||||
item_charges tinyint(2) default 1 not null, equip_item tinyint(2) unsigned not null,
|
||||
chance tinyint(2) unsigned default 1 not null, primary key (lootdrop_id, item_id));
|
||||
|
||||
ALTER TABLE `loottable_entries` ADD `probability` FLOAT NOT NULL DEFAULT '100';
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LOOTTABLE_H
|
||||
#define LOOTTABLE_H
|
||||
#include "zonedump.h"
|
||||
#include "../common/linked_list.h"
|
||||
|
||||
#include <list>
|
||||
using namespace std;
|
||||
|
||||
#pragma pack(1)
|
||||
struct LootTableEntries_Struct {
|
||||
uint32 lootdrop_id;
|
||||
uint8 droplimit;
|
||||
uint8 mindrop;
|
||||
uint8 multiplier;
|
||||
float probability;
|
||||
};
|
||||
|
||||
struct LootTable_Struct {
|
||||
uint32 mincash;
|
||||
uint32 maxcash;
|
||||
uint32 avgcoin;
|
||||
uint32 NumEntries;
|
||||
LootTableEntries_Struct Entries[0];
|
||||
};
|
||||
|
||||
struct LootDropEntries_Struct {
|
||||
uint32 item_id;
|
||||
int8 item_charges;
|
||||
uint8 equip_item;
|
||||
float chance;
|
||||
uint8 minlevel;
|
||||
uint8 maxlevel;
|
||||
uint8 multiplier;
|
||||
};
|
||||
|
||||
struct LootDrop_Struct {
|
||||
uint32 NumEntries;
|
||||
LootDropEntries_Struct Entries[0];
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
typedef list<ServerLootItem_Struct*> ItemList;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,606 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "../common/debug.h"
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
#include <stdlib.h>
|
||||
#include "npc.h"
|
||||
#include "masterentity.h"
|
||||
#include "zonedb.h"
|
||||
#include "../common/MiscFunctions.h"
|
||||
#ifdef _WINDOWS
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#include "../common/EMuShareMem.h"
|
||||
extern LoadEMuShareMemDLL EMuShareMemDLL;
|
||||
bool SharedDatabase::extDBLoadLoot() {
|
||||
return s_usedb->DBLoadLoot();
|
||||
}
|
||||
|
||||
bool SharedDatabase::LoadLoot() {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
uint32 tmpLootTableCount = 0;
|
||||
uint32 tmpLootTableEntriesCount = 0;
|
||||
uint32 tmpLootDropCount = 0;
|
||||
uint32 tmpLootDropEntriesCount = 0;
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT max(id), count(*) FROM loottable"), errbuf, &result)) {
|
||||
safe_delete_array(query);
|
||||
if (mysql_num_rows(result) == 1) {
|
||||
row = mysql_fetch_row(result);
|
||||
if (row[0])
|
||||
loottable_max = atoi(row[0]);
|
||||
else
|
||||
loottable_max = 0;
|
||||
tmpLootTableCount = atoi(row[1]);
|
||||
}
|
||||
else {
|
||||
mysql_free_result(result);
|
||||
return false;
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else {
|
||||
cerr << "Error in LoadLoot query, loottable part: '" << query << "' " << errbuf << endl;
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT count(*) FROM loottable_entries"), errbuf, &result)) {
|
||||
safe_delete_array(query);
|
||||
if (mysql_num_rows(result) == 1) {
|
||||
row = mysql_fetch_row(result);
|
||||
tmpLootTableEntriesCount = atoi(row[0]);
|
||||
}
|
||||
else {
|
||||
mysql_free_result(result);
|
||||
return false;
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else {
|
||||
cerr << "Error in LoadLoot query, loottable2 part: '" << query << "' " << errbuf << endl;
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT max(id), count(*) FROM lootdrop"), errbuf, &result)) {
|
||||
safe_delete_array(query);
|
||||
if (mysql_num_rows(result) == 1) {
|
||||
row = mysql_fetch_row(result);
|
||||
if (row[0])
|
||||
lootdrop_max = atoi(row[0]);
|
||||
else
|
||||
lootdrop_max = 0;
|
||||
tmpLootDropCount = atoi(row[1]);
|
||||
}
|
||||
else {
|
||||
mysql_free_result(result);
|
||||
return false;
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else {
|
||||
cerr << "Error in LoadLoot query, lootdrop1 part: '" << query << "' " << errbuf << endl;
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT max(lootdrop_id), count(*) FROM lootdrop_entries"), errbuf, &result)) {
|
||||
safe_delete_array(query);
|
||||
if (mysql_num_rows(result) == 1) {
|
||||
row = mysql_fetch_row(result);
|
||||
tmpLootDropEntriesCount = atoi(row[1]);
|
||||
}
|
||||
else {
|
||||
mysql_free_result(result);
|
||||
return false;
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else {
|
||||
cerr << "Error in LoadLoot query, lootdrop part: '" << query << "' " << errbuf << endl;
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
return EMuShareMemDLL.Loot.DLLLoadLoot(&extDBLoadLoot,
|
||||
sizeof(LootTable_Struct), tmpLootTableCount, loottable_max,
|
||||
sizeof(LootTableEntries_Struct), tmpLootTableEntriesCount,
|
||||
sizeof(LootDrop_Struct), tmpLootDropCount, lootdrop_max,
|
||||
sizeof(LootDropEntries_Struct), tmpLootDropEntriesCount);
|
||||
}
|
||||
|
||||
bool SharedDatabase::DBLoadLoot() {
|
||||
LogFile->write(EQEMuLog::Status, "Loading Loot tables from database...");
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
MYSQL_RES *result2;
|
||||
uint32 i, tmpid = 0, tmpmincash = 0, tmpmaxcash = 0, tmpavgcoin = 0;
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, mincash, maxcash, avgcoin FROM loottable"), errbuf, &result)) {
|
||||
safe_delete_array(query);
|
||||
LootTable_Struct* tmpLT = 0;
|
||||
while ((row = mysql_fetch_row(result))) {
|
||||
tmpid = atoi(row[0]);
|
||||
tmpmincash = atoi(row[1]);
|
||||
tmpmaxcash = atoi(row[2]);
|
||||
tmpavgcoin = atoi(row[3]);
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT loottable_id, lootdrop_id, droplimit, mindrop, multiplier, probability FROM loottable_entries WHERE loottable_id=%i", tmpid), errbuf, &result2)) {
|
||||
safe_delete_array(query);
|
||||
tmpLT = (LootTable_Struct*) new uchar[sizeof(LootTable_Struct) + (sizeof(LootTableEntries_Struct) * mysql_num_rows(result2))];
|
||||
memset(tmpLT, 0, sizeof(LootTable_Struct) + (sizeof(LootTableEntries_Struct) * mysql_num_rows(result2)));
|
||||
tmpLT->NumEntries = mysql_num_rows(result2);
|
||||
tmpLT->mincash = tmpmincash;
|
||||
tmpLT->maxcash = tmpmaxcash;
|
||||
tmpLT->avgcoin = tmpavgcoin;
|
||||
i=0;
|
||||
while ((row = mysql_fetch_row(result2))) {
|
||||
if (i >= tmpLT->NumEntries) {
|
||||
mysql_free_result(result);
|
||||
mysql_free_result(result2);
|
||||
safe_delete_array(tmpLT);
|
||||
cerr << "Error in ZoneDatabase::DBLoadLoot, i >= NumEntries" << endl;
|
||||
return false;
|
||||
}
|
||||
tmpLT->Entries[i].lootdrop_id = atoi(row[1]);
|
||||
tmpLT->Entries[i].droplimit = atoi(row[2]);
|
||||
tmpLT->Entries[i].mindrop = atoi(row[3]);
|
||||
tmpLT->Entries[i].multiplier = atoi(row[4]);
|
||||
tmpLT->Entries[i].probability = atof(row[5]);
|
||||
i++;
|
||||
}
|
||||
if (!EMuShareMemDLL.Loot.cbAddLootTable(tmpid, tmpLT)) {
|
||||
mysql_free_result(result);
|
||||
mysql_free_result(result2);
|
||||
safe_delete_array(tmpLT);
|
||||
cout << "Error in ZoneDatabase::DBLoadLoot: !cbAddLootTable(" << tmpid << ")" << endl;
|
||||
return false;
|
||||
}
|
||||
safe_delete_array(tmpLT);
|
||||
mysql_free_result(result2);
|
||||
}
|
||||
else {
|
||||
mysql_free_result(result);
|
||||
cerr << "Error in LoadLoot (memshare) #1 query '" << query << "' " << errbuf << endl;
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else {
|
||||
cerr << "Error in LoadLoot (memshare) #2 query '" << query << "' " << errbuf << endl;
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT id FROM lootdrop", tmpid), errbuf, &result)) {
|
||||
safe_delete_array(query);
|
||||
LootDrop_Struct* tmpLD = 0;
|
||||
while ((row = mysql_fetch_row(result))) {
|
||||
tmpid = atoi(row[0]);
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT lootdrop_id, item_id, item_charges, equip_item, chance, minlevel, maxlevel, multiplier FROM lootdrop_entries WHERE lootdrop_id=%i order by chance desc", tmpid), errbuf, &result2)) {
|
||||
safe_delete_array(query);
|
||||
tmpLD = (LootDrop_Struct*) new uchar[sizeof(LootDrop_Struct) + (sizeof(LootDropEntries_Struct) * mysql_num_rows(result2))];
|
||||
memset(tmpLD, 0, sizeof(LootDrop_Struct) + (sizeof(LootDropEntries_Struct) * mysql_num_rows(result2)));
|
||||
tmpLD->NumEntries = mysql_num_rows(result2);
|
||||
i=0;
|
||||
while ((row = mysql_fetch_row(result2))) {
|
||||
if (i >= tmpLD->NumEntries) {
|
||||
mysql_free_result(result);
|
||||
mysql_free_result(result2);
|
||||
safe_delete_array(tmpLD);
|
||||
cerr << "Error in ZoneDatabase::DBLoadLoot, i >= NumEntries" << endl;
|
||||
return false;
|
||||
}
|
||||
tmpLD->Entries[i].item_id = atoi(row[1]);
|
||||
tmpLD->Entries[i].item_charges = atoi(row[2]);
|
||||
tmpLD->Entries[i].equip_item = atoi(row[3]);
|
||||
tmpLD->Entries[i].chance = atof(row[4]);
|
||||
tmpLD->Entries[i].minlevel = atoi(row[5]);
|
||||
tmpLD->Entries[i].maxlevel = atoi(row[6]);
|
||||
tmpLD->Entries[i].multiplier = atoi(row[7]);
|
||||
i++;
|
||||
}
|
||||
if (!EMuShareMemDLL.Loot.cbAddLootDrop(tmpid, tmpLD)) {
|
||||
mysql_free_result(result);
|
||||
mysql_free_result(result2);
|
||||
safe_delete_array(tmpLD);
|
||||
cout << "Error in ZoneDatabase::DBLoadLoot: !cbAddLootDrop(" << tmpid << ")" << endl;
|
||||
return false;
|
||||
}
|
||||
safe_delete_array(tmpLD);
|
||||
mysql_free_result(result2);
|
||||
}
|
||||
else {
|
||||
cerr << "Error in LoadLoot (memshare) #3 query '" << query << "' " << errbuf << endl;
|
||||
mysql_free_result(result);
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else {
|
||||
cerr << "Error in LoadLoot (memshare) #4 query '" << query << "' " << errbuf << endl;
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const LootTable_Struct* SharedDatabase::GetLootTable(uint32 loottable_id) {
|
||||
return EMuShareMemDLL.Loot.GetLootTable(loottable_id);
|
||||
}
|
||||
|
||||
const LootDrop_Struct* SharedDatabase::GetLootDrop(uint32 lootdrop_id) {
|
||||
return EMuShareMemDLL.Loot.GetLootDrop(lootdrop_id);
|
||||
}
|
||||
|
||||
// Queries the loottable: adds item & coin to the npc
|
||||
void ZoneDatabase::AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* itemlist, uint32* copper, uint32* silver, uint32* gold, uint32* plat) {
|
||||
_ZP(Database_AddLootTableToNPC);
|
||||
//if (loottable_id == 178190)
|
||||
//DebugBreak();
|
||||
const LootTable_Struct* lts = 0;
|
||||
*copper = 0;
|
||||
*silver = 0;
|
||||
*gold = 0;
|
||||
*plat = 0;
|
||||
|
||||
lts = database.GetLootTable(loottable_id);
|
||||
if (!lts)
|
||||
return;
|
||||
|
||||
// do coin
|
||||
if (lts->mincash > lts->maxcash) {
|
||||
cerr << "Error in loottable #" << loottable_id << ": mincash > maxcash" << endl;
|
||||
}
|
||||
else if (lts->maxcash != 0) {
|
||||
uint32 cash = 0;
|
||||
if (lts->mincash == lts->maxcash)
|
||||
cash = lts->mincash;
|
||||
else
|
||||
cash = MakeRandomInt(lts->mincash, lts->maxcash);
|
||||
if (cash != 0) {
|
||||
if (lts->avgcoin != 0) {
|
||||
//this is some crazy ass stuff... and makes very little sense... dont use it, k?
|
||||
uint32 mincoin = (uint32) (lts->avgcoin * 0.75 + 1);
|
||||
uint32 maxcoin = (uint32) (lts->avgcoin * 1.25 + 1);
|
||||
*copper = MakeRandomInt(mincoin, maxcoin);
|
||||
*silver = MakeRandomInt(mincoin, maxcoin);
|
||||
*gold = MakeRandomInt(mincoin, maxcoin);
|
||||
if(*copper > cash) { *copper = cash; }
|
||||
cash -= *copper;
|
||||
if(*silver>(cash/10)) { *silver = (cash/10); }
|
||||
cash -= *silver*10;
|
||||
if(*gold > (cash/100)) { *gold = (cash/100); }
|
||||
cash -= *gold*100;
|
||||
}
|
||||
if (cash < 0) {
|
||||
cash = 0;
|
||||
}
|
||||
*plat = cash / 1000;
|
||||
cash -= *plat * 1000;
|
||||
uint32 gold2 = cash / 100;
|
||||
cash -= gold2 * 100;
|
||||
uint32 silver2 = cash / 10;
|
||||
cash -= silver2 * 10;
|
||||
*gold += gold2;
|
||||
*silver += silver2;
|
||||
*copper += cash;
|
||||
}
|
||||
}
|
||||
|
||||
// Do items
|
||||
for (uint32 i=0; i<lts->NumEntries; i++) {
|
||||
for (uint32 k = 1; k <= lts->Entries[i].multiplier; k++) {
|
||||
uint8 droplimit = lts->Entries[i].droplimit;
|
||||
uint8 mindrop = lts->Entries[i].mindrop;
|
||||
|
||||
//LootTable Entry probability
|
||||
float ltchance = 0.0f;
|
||||
ltchance = lts->Entries[i].probability;
|
||||
|
||||
float drop_chance = 0.0f;
|
||||
if(ltchance > 0.0 && ltchance < 100.0) {
|
||||
drop_chance = MakeRandomFloat(0.0, 100.0);
|
||||
}
|
||||
|
||||
if (ltchance != 0.0 && (ltchance == 100.0 || drop_chance < ltchance)) {
|
||||
AddLootDropToNPC(npc,lts->Entries[i].lootdrop_id, itemlist, droplimit, mindrop);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Called by AddLootTableToNPC
|
||||
// maxdrops = size of the array npcd
|
||||
void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* itemlist, uint8 droplimit, uint8 mindrop) {
|
||||
const LootDrop_Struct* lds = GetLootDrop(lootdrop_id);
|
||||
if (!lds) {
|
||||
return;
|
||||
}
|
||||
if(lds->NumEntries == 0) //nothing possible to add
|
||||
return;
|
||||
|
||||
// Too long a list needs to be limited.
|
||||
if(lds->NumEntries > 99 && droplimit < 1)
|
||||
droplimit = lds->NumEntries/100;
|
||||
|
||||
uint8 limit = 0;
|
||||
// Start at a random point in itemlist.
|
||||
uint32 item = MakeRandomInt(0, lds->NumEntries-1);
|
||||
// Main loop.
|
||||
for (uint32 i=0; i<lds->NumEntries;)
|
||||
{
|
||||
//Force the itemlist back to beginning.
|
||||
if (item > (lds->NumEntries-1))
|
||||
item = 0;
|
||||
|
||||
uint8 charges = lds->Entries[item].multiplier;
|
||||
uint8 pickedcharges = 0;
|
||||
// Loop to check multipliers.
|
||||
for (uint32 x=1; x<=charges; x++)
|
||||
{
|
||||
// Actual roll.
|
||||
float thischance = 0.0;
|
||||
thischance = lds->Entries[item].chance;
|
||||
|
||||
float drop_chance = 0.0;
|
||||
if(thischance != 100.0)
|
||||
drop_chance = MakeRandomFloat(0.0, 100.0);
|
||||
|
||||
#if EQDEBUG>=11
|
||||
LogFile->write(EQEMuLog::Debug, "Drop chance for npc: %s, this chance:%f, drop roll:%f", npc->GetName(), thischance, drop_chance);
|
||||
#endif
|
||||
if (thischance == 100.0 || drop_chance < thischance)
|
||||
{
|
||||
uint32 itemid = lds->Entries[item].item_id;
|
||||
|
||||
const Item_Struct* dbitem = GetItem(itemid);
|
||||
npc->AddLootDrop(dbitem, itemlist, lds->Entries[item].item_charges, lds->Entries[item].minlevel, lds->Entries[item].maxlevel, lds->Entries[item].equip_item, false);
|
||||
pickedcharges++;
|
||||
}
|
||||
}
|
||||
// Items with multipliers only count as 1 towards the limit.
|
||||
if(pickedcharges > 0)
|
||||
limit++;
|
||||
|
||||
// If true, limit reached.
|
||||
if(limit >= droplimit && droplimit > 0)
|
||||
break;
|
||||
|
||||
item++;
|
||||
i++;
|
||||
|
||||
// We didn't reach our minimium, run loop again.
|
||||
if(i == lds->NumEntries){
|
||||
if(limit < mindrop){
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
} // We either ran out of items or reached our limit.
|
||||
}
|
||||
|
||||
//if itemlist is null, just send wear changes
|
||||
void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange) {
|
||||
if(item2 == NULL)
|
||||
return;
|
||||
|
||||
//make sure we are doing something...
|
||||
if(!itemlist && !wearchange)
|
||||
return;
|
||||
|
||||
ServerLootItem_Struct* item = new ServerLootItem_Struct;
|
||||
#if EQDEBUG>=11
|
||||
LogFile->write(EQEMuLog::Debug, "Adding drop to npc: %s, Item: %i", GetName(), item2->ID);
|
||||
#endif
|
||||
|
||||
EQApplicationPacket* outapp = NULL;
|
||||
WearChange_Struct* wc = NULL;
|
||||
if(wearchange) {
|
||||
outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct));
|
||||
wc = (WearChange_Struct*)outapp->pBuffer;
|
||||
wc->spawn_id = GetID();
|
||||
wc->material=0;
|
||||
}
|
||||
|
||||
item->item_id = item2->ID;
|
||||
item->charges = charges;
|
||||
item->aug1 = 0;
|
||||
item->aug2 = 0;
|
||||
item->aug3 = 0;
|
||||
item->aug4 = 0;
|
||||
item->aug5 = 0;
|
||||
item->minlevel = minlevel;
|
||||
item->maxlevel = maxlevel;
|
||||
if (equipit) {
|
||||
uint8 eslot = 0xFF;
|
||||
char newid[20];
|
||||
const Item_Struct* compitem = NULL;
|
||||
bool found = false; // track if we found an empty slot we fit into
|
||||
int32 foundslot = -1; // for multi-slot items
|
||||
|
||||
// Equip rules are as follows:
|
||||
// If the item has the NoPet flag set it will not be equipped.
|
||||
// An empty slot takes priority. The first empty one that an item can
|
||||
// fit into will be the one picked for the item.
|
||||
// AC is the primary choice for which item gets picked for a slot.
|
||||
// If AC is identical HP is considered next.
|
||||
// If an item can fit into multiple slots we'll pick the last one where
|
||||
// it is an improvement.
|
||||
|
||||
if (!item2->NoPet) {
|
||||
for (int i=0; !found && i<MAX_WORN_INVENTORY; i++) {
|
||||
uint32 slots = (1 << i);
|
||||
if (item2->Slots & slots) {
|
||||
if(equipment[i])
|
||||
{
|
||||
compitem = database.GetItem(equipment[i]);
|
||||
if (item2->AC > compitem->AC ||
|
||||
(item2->AC == compitem->AC && item2->HP > compitem->HP))
|
||||
{
|
||||
// item would be an upgrade
|
||||
// check if we're multi-slot, if yes then we have to keep
|
||||
// looking in case any of the other slots we can fit into are empty.
|
||||
if (item2->Slots != slots) {
|
||||
foundslot = i;
|
||||
}
|
||||
else {
|
||||
equipment[i] = item2->ID;
|
||||
foundslot = i;
|
||||
found = true;
|
||||
}
|
||||
} // end if ac
|
||||
}
|
||||
else
|
||||
{
|
||||
equipment[i] = item2->ID;
|
||||
foundslot = i;
|
||||
found = true;
|
||||
}
|
||||
} // end if (slots)
|
||||
} // end for
|
||||
} // end if NoPet
|
||||
|
||||
// Possible slot was found but not selected. Pick it now.
|
||||
if (!found && foundslot >= 0) {
|
||||
equipment[foundslot] = item2->ID;
|
||||
found = true;
|
||||
}
|
||||
|
||||
// @merth: IDFile size has been increased, this needs to change
|
||||
uint16 emat;
|
||||
if(item2->Material <= 0
|
||||
|| item2->Slots & (1 << SLOT_PRIMARY | 1 << SLOT_SECONDARY)) {
|
||||
memset(newid, 0, sizeof(newid));
|
||||
for(int i=0;i<7;i++){
|
||||
if (!isalpha(item2->IDFile[i])){
|
||||
strn0cpy(newid, &item2->IDFile[i],6);
|
||||
i=8;
|
||||
}
|
||||
}
|
||||
|
||||
emat = atoi(newid);
|
||||
} else {
|
||||
emat = item2->Material;
|
||||
}
|
||||
|
||||
if (foundslot == SLOT_PRIMARY) {
|
||||
if (item2->Proc.Effect != 0)
|
||||
CastToMob()->AddProcToWeapon(item2->Proc.Effect, true);
|
||||
|
||||
eslot = MATERIAL_PRIMARY;
|
||||
}
|
||||
else if (foundslot == SLOT_SECONDARY
|
||||
&& (GetOwner() != NULL || (GetLevel() >= 13 && MakeRandomInt(0,99) < NPC_DW_CHANCE) || (item2->Damage==0)) &&
|
||||
(item2->ItemType == ItemType1HS || item2->ItemType == ItemType1HB || item2->ItemType == ItemTypeShield ||
|
||||
item2->ItemType == ItemTypePierce))
|
||||
{
|
||||
if (item2->Proc.Effect!=0)
|
||||
CastToMob()->AddProcToWeapon(item2->Proc.Effect, true);
|
||||
|
||||
eslot = MATERIAL_SECONDARY;
|
||||
}
|
||||
else if (foundslot == SLOT_HEAD) {
|
||||
eslot = MATERIAL_HEAD;
|
||||
}
|
||||
else if (foundslot == SLOT_CHEST) {
|
||||
eslot = MATERIAL_CHEST;
|
||||
}
|
||||
else if (foundslot == SLOT_ARMS) {
|
||||
eslot = MATERIAL_ARMS;
|
||||
}
|
||||
else if (foundslot == SLOT_BRACER01 || foundslot == SLOT_BRACER02) {
|
||||
eslot = MATERIAL_BRACER;
|
||||
}
|
||||
else if (foundslot == SLOT_HANDS) {
|
||||
eslot = MATERIAL_HANDS;
|
||||
}
|
||||
else if (foundslot == SLOT_LEGS) {
|
||||
eslot = MATERIAL_LEGS;
|
||||
}
|
||||
else if (foundslot == SLOT_FEET) {
|
||||
eslot = MATERIAL_FEET;
|
||||
}
|
||||
|
||||
/*
|
||||
what was this about???
|
||||
|
||||
if (((npc->GetRace()==127) && (npc->CastToMob()->GetOwnerID()!=0)) && (item2->Slots==24576) || (item2->Slots==8192) || (item2->Slots==16384)){
|
||||
npc->d_meele_texture2=atoi(newid);
|
||||
wc->wear_slot_id=8;
|
||||
if (item2->Material >0)
|
||||
wc->material=item2->Material;
|
||||
else
|
||||
wc->material=atoi(newid);
|
||||
npc->AC+=item2->AC;
|
||||
npc->STR+=item2->STR;
|
||||
npc->INT+=item2->INT;
|
||||
}
|
||||
*/
|
||||
|
||||
//if we found an open slot it goes in...
|
||||
if(eslot != 0xFF) {
|
||||
if(wearchange) {
|
||||
wc->wear_slot_id = eslot;
|
||||
wc->material = emat;
|
||||
}
|
||||
|
||||
}
|
||||
if (found) {
|
||||
CalcBonuses(); // This is less than ideal for bulk adding of items
|
||||
}
|
||||
item->equipSlot = item2->Slots;
|
||||
}
|
||||
|
||||
if(itemlist != NULL)
|
||||
itemlist->push_back(item);
|
||||
else
|
||||
safe_delete(item);
|
||||
|
||||
if(wearchange && outapp) {
|
||||
entity_list.QueueClients(this, outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
}
|
||||
|
||||
void NPC::AddItem(const Item_Struct* item, uint16 charges, bool equipitem) {
|
||||
//slot isnt needed, its determined from the item.
|
||||
AddLootDrop(item, &itemlist, charges, 1, 127, equipitem, equipitem);
|
||||
}
|
||||
|
||||
void NPC::AddItem(uint32 itemid, uint16 charges, bool equipitem) {
|
||||
//slot isnt needed, its determined from the item.
|
||||
const Item_Struct * i = database.GetItem(itemid);
|
||||
if(i == NULL)
|
||||
return;
|
||||
AddLootDrop(i, &itemlist, charges, 1, 127, equipitem, equipitem);
|
||||
}
|
||||
|
||||
void NPC::AddLootTable() {
|
||||
if (npctype_id != 0) { // check if it's a GM spawn
|
||||
database.AddLootTableToNPC(this,loottable_id, &itemlist, &copper, &silver, &gold, &platinum);
|
||||
}
|
||||
}
|
||||
|
||||
+190
@@ -0,0 +1,190 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef MAP_H
|
||||
#define MAP_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
//this is the current version number to expect from the map header
|
||||
#define MAP_VERSION 0x01000000
|
||||
|
||||
#define BEST_Z_INVALID -999999
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
typedef struct _vertex{
|
||||
// unsigned long order;
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
|
||||
_vertex()
|
||||
{
|
||||
x = y = z = 0.0f;
|
||||
};
|
||||
|
||||
_vertex(float ix, float iy, float iz)
|
||||
{
|
||||
x = ix;
|
||||
y = iy;
|
||||
z = iz;
|
||||
}
|
||||
bool operator==(const _vertex &v1) const
|
||||
{
|
||||
return((v1.x == x) && (v1.y == y) && (v1.z ==z));
|
||||
}
|
||||
|
||||
}VERTEX, *PVERTEX;
|
||||
|
||||
typedef struct _face{
|
||||
// unsigned long a, b, c; //vertexs
|
||||
VERTEX a;
|
||||
VERTEX b;
|
||||
VERTEX c;
|
||||
float nx, ny, nz, nd;
|
||||
}FACE, *PFACE;
|
||||
|
||||
typedef struct _mapHeader {
|
||||
uint32 version;
|
||||
uint32 face_count;
|
||||
uint16 node_count;
|
||||
uint32 facelist_count;
|
||||
} mapHeader;
|
||||
|
||||
/*
|
||||
This is used for the recursive node structure
|
||||
unsigned shorts are adequate because, worst case
|
||||
even in a zone that is 6000x6000 with a small node
|
||||
size of 30x30, there are only 40000 nodes.
|
||||
|
||||
quadrent definitions:
|
||||
quad 1 (nodes[0]):
|
||||
x>=0, y>=0
|
||||
quad 2 (nodes[1]):
|
||||
x<0, y>=0
|
||||
quad 3 (nodes[2]):
|
||||
x<0, y<0
|
||||
quad 4 (nodes[3]):
|
||||
x>=0, y<0
|
||||
|
||||
*/
|
||||
enum { //node flags
|
||||
nodeFinal = 0x01
|
||||
//7 more bits if theres something to use them for...
|
||||
};
|
||||
typedef struct _nodeHeader {
|
||||
//bounding box of this node
|
||||
//there is no reason that these could not be unsigned
|
||||
//shorts other than we have to compare them to floats
|
||||
//all over the place, so they stay floats for now.
|
||||
//changing it could save 8 bytes per node record (~320k for huge maps)
|
||||
float minx;
|
||||
float miny;
|
||||
float maxx;
|
||||
float maxy;
|
||||
|
||||
uint8 flags;
|
||||
union {
|
||||
uint16 nodes[4]; //index 0 means NULL, not root
|
||||
struct {
|
||||
uint32 count;
|
||||
uint32 offset;
|
||||
} faces;
|
||||
};
|
||||
} nodeHeader, NODE, *PNODE;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
//special value returned as 'not found'
|
||||
#define NODE_NONE 65534
|
||||
#define MAP_ROOT_NODE 0
|
||||
|
||||
typedef uint16 NodeRef;
|
||||
|
||||
/*typedef struct _node {
|
||||
nodeHeader head;
|
||||
unsigned int * pfaces;
|
||||
char mask;
|
||||
struct _node * node1, *node2, *node3, *node4;
|
||||
}NODE, *PNODE;*/
|
||||
|
||||
class Map {
|
||||
public:
|
||||
static Map* LoadMapfile(const char* in_zonename, const char *directory = NULL);
|
||||
|
||||
Map();
|
||||
~Map();
|
||||
|
||||
bool loadMap(FILE *fp);
|
||||
|
||||
//the result is always final, except special NODE_NONE
|
||||
NodeRef SeekNode( NodeRef _node, float x, float y ) const;
|
||||
|
||||
//these are untested since rewrite:
|
||||
int *SeekFace( NodeRef _node, float x, float y );
|
||||
float GetFaceHeight( int _idx, float x, float y ) const;
|
||||
|
||||
bool LocWithinNode( NodeRef _node, float x, float y ) const;
|
||||
|
||||
//nodes to these functions must be final
|
||||
bool LineIntersectsNode( NodeRef _node, VERTEX start, VERTEX end, VERTEX *result, FACE **on = NULL) const;
|
||||
bool LineIntersectsFace( PFACE cface, VERTEX start, VERTEX end, VERTEX *result) const;
|
||||
float FindBestZ( NodeRef _node, VERTEX start, VERTEX *result, FACE **on = NULL) const;
|
||||
bool LineIntersectsZone(VERTEX start, VERTEX end, float step, VERTEX *result, FACE **on = NULL) const;
|
||||
|
||||
// inline unsigned int GetVertexNumber( ) {return m_Vertex; }
|
||||
inline uint32 GetFacesNumber( ) const { return m_Faces; }
|
||||
// inline PVERTEX GetVertex( int _idx ) {return mFinalVertex + _idx; }
|
||||
inline PFACE GetFace( int _idx) {return mFinalFaces + _idx; }
|
||||
inline PFACE GetFaceFromlist( int _idx) {return &mFinalFaces[ mFaceLists[_idx] ]; }
|
||||
inline NodeRef GetRoot( ) const { return MAP_ROOT_NODE; }
|
||||
inline PNODE GetNode( NodeRef r ) { return( mNodes + r ); }
|
||||
|
||||
inline float GetMinX() const { return(_minx); }
|
||||
inline float GetMaxX() const { return(_maxx); }
|
||||
inline float GetMinY() const { return(_miny); }
|
||||
inline float GetMaxY() const { return(_maxy); }
|
||||
inline float GetMinZ() const { return(_minz); }
|
||||
inline float GetMaxZ() const { return(_maxz); }
|
||||
bool LineIntersectsZoneNoZLeaps(VERTEX start, VERTEX end, float step_mag, VERTEX *result, FACE **on);
|
||||
float FindClosestZ(VERTEX p ) const;
|
||||
|
||||
private:
|
||||
// unsigned long m_Vertex;
|
||||
uint32 m_Faces;
|
||||
uint32 m_Nodes;
|
||||
uint32 m_FaceLists;
|
||||
// PVERTEX mFinalVertex;
|
||||
PFACE mFinalFaces;
|
||||
PNODE mNodes;
|
||||
uint32 *mFaceLists;
|
||||
|
||||
|
||||
int mCandFaces[100];
|
||||
|
||||
float _minz, _maxz;
|
||||
float _minx, _miny, _maxx, _maxy;
|
||||
|
||||
static void Normalize(VERTEX *p);
|
||||
|
||||
// void RecLoadNode( PNODE _node, FILE *l_f );
|
||||
// void RecFreeNode( PNODE _node );
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
//Trumpcard: EntityLists are composed of multiple list types. This is the
|
||||
//master that includes all types. When entity.h is required, many of these are as well.
|
||||
|
||||
#include "entity.h"
|
||||
#include "groups.h"
|
||||
#include "raids.h"
|
||||
#include "client.h"
|
||||
#include "object.h"
|
||||
#include "PlayerCorpse.h"
|
||||
#include "doors.h"
|
||||
#include "mob.h"
|
||||
#include "trap.h"
|
||||
#include "beacon.h"
|
||||
#include "horse.h"
|
||||
|
||||
#ifdef BOTS
|
||||
#include "bot.h"
|
||||
#endif
|
||||
|
||||
+2338
File diff suppressed because it is too large
Load Diff
+4507
File diff suppressed because it is too large
Load Diff
+352
@@ -0,0 +1,352 @@
|
||||
#ifndef MERC_H
|
||||
#define MERC_H
|
||||
#include "mob.h"
|
||||
#include "zonedb.h"
|
||||
#include "npc.h"
|
||||
using namespace std;
|
||||
|
||||
#define MERC_DEBUG 0
|
||||
#define TANK 1
|
||||
#define HEALER 2
|
||||
#define MELEEDPS 9
|
||||
#define CASTERDPS 12
|
||||
const int MercAISpellRange = 100; // TODO: Write a method that calcs what the merc's spell range is based on spell, equipment, AA, whatever and replace this
|
||||
|
||||
enum MercStanceType {
|
||||
MercStancePassive = 1,
|
||||
MercStanceBalanced,
|
||||
MercStanceEfficient,
|
||||
MercStanceReactive,
|
||||
MercStanceAggressive,
|
||||
MercStanceAssist,
|
||||
MercStanceBurn,
|
||||
MercStanceEfficient2,
|
||||
MercStanceBurnAE
|
||||
};
|
||||
|
||||
struct MercSpell {
|
||||
uint16 spellid; // <= 0 = no spell
|
||||
uint16 type; // 0 = never, must be one (and only one) of the defined values
|
||||
int16 stance; // 0 = all, + = only this stance, - = all except this stance
|
||||
int16 slot;
|
||||
uint16 proc_chance;
|
||||
uint32 time_cancast; // when we can cast this spell next
|
||||
};
|
||||
|
||||
struct MercTimer {
|
||||
uint16 timerid; // EndurTimerIndex
|
||||
uint8 timertype; // 1 = spell, 2 = disc
|
||||
uint16 spellid; // <= 0 = no spell
|
||||
uint32 time_cancast; // when we can cast this spell next
|
||||
};
|
||||
|
||||
class Merc : public NPC {
|
||||
public:
|
||||
Merc(const NPCType* d, float x, float y, float z, float heading);
|
||||
virtual ~Merc();
|
||||
|
||||
//abstract virtual function implementations requird by base abstract class
|
||||
virtual void Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillType attack_skill);
|
||||
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false);
|
||||
virtual bool Attack(Mob* other, int Hand = SLOT_PRIMARY, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false);
|
||||
virtual bool HasRaid() { return false; }
|
||||
virtual bool HasGroup() { return (GetGroup() ? true : false); }
|
||||
virtual Raid* GetRaid() { return 0; }
|
||||
virtual Group* GetGroup() { return entity_list.GetGroupByMob(this); }
|
||||
|
||||
// Mob AI Virtual Override Methods
|
||||
virtual void AI_Start(int32 iMoveDelay = 0);
|
||||
virtual void AI_Stop();
|
||||
virtual void AI_Process();
|
||||
|
||||
//virtual bool AICastSpell(Mob* tar, int8 iChance, int16 iSpellTypes);
|
||||
virtual bool AICastSpell(int8 iChance, int16 iSpellTypes);
|
||||
virtual bool AIDoSpellCast(uint16 spellid, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0);
|
||||
virtual bool AI_EngagedCastCheck();
|
||||
//virtual bool AI_PursueCastCheck();
|
||||
virtual bool AI_IdleCastCheck();
|
||||
|
||||
virtual bool Process();
|
||||
|
||||
// Static Merc Group Methods
|
||||
static bool AddMercToGroup(Merc* merc, Group* group);
|
||||
static bool RemoveMercFromGroup(Merc* merc, Group* group);
|
||||
void ProcessClientZoneChange(Client* mercOwner);
|
||||
static void MercGroupSay(Mob *speaker, const char *msg, ...);
|
||||
|
||||
// Merc Spell Casting Methods
|
||||
int8 GetChanceToCastBySpellType(int16 spellType);
|
||||
void SetSpellRecastTimer(uint16 timer_id, uint16 spellid, uint32 recast_delay);
|
||||
void SetDisciplineRecastTimer(uint16 timer_id, uint16 spellid, uint32 recast_delay);
|
||||
static int32 GetSpellRecastTimer(Merc *caster, uint16 timer_id);
|
||||
static bool CheckSpellRecastTimers(Merc *caster, uint16 spellid);
|
||||
static int32 GetDisciplineRecastTimer(Merc *caster, uint16 timer_id);
|
||||
static bool CheckDisciplineRecastTimers(Merc *caster, uint16 spellid);
|
||||
static int32 GetDisciplineRemainingTime(Merc *caster, uint16 timer_id);
|
||||
static std::list<MercSpell> GetMercSpellsForSpellEffect(Merc* caster, int spellEffect);
|
||||
static std::list<MercSpell> GetMercSpellsForSpellEffectAndTargetType(Merc* caster, int spellEffect, SpellTargetType targetType);
|
||||
static std::list<MercSpell> GetMercSpellsBySpellType(Merc* caster, int spellType);
|
||||
static MercSpell GetFirstMercSpellBySpellType(Merc* caster, int spellType);
|
||||
static MercSpell GetFirstMercSpellForSingleTargetHeal(Merc* caster);
|
||||
static MercSpell GetMercSpellBySpellID(Merc* caster, uint16 spellid);
|
||||
static MercSpell GetBestMercSpellForVeryFastHeal(Merc* caster);
|
||||
static MercSpell GetBestMercSpellForFastHeal(Merc* caster);
|
||||
static MercSpell GetBestMercSpellForHealOverTime(Merc* caster);
|
||||
static MercSpell GetBestMercSpellForPercentageHeal(Merc* caster);
|
||||
static MercSpell GetBestMercSpellForRegularSingleTargetHeal(Merc* caster);
|
||||
static MercSpell GetBestMercSpellForGroupHealOverTime(Merc* caster);
|
||||
static MercSpell GetBestMercSpellForGroupCompleteHeal(Merc* caster);
|
||||
static MercSpell GetBestMercSpellForGroupHeal(Merc* caster);
|
||||
static MercSpell GetBestMercSpellForAETaunt(Merc* caster);
|
||||
static MercSpell GetBestMercSpellForTaunt(Merc* caster);
|
||||
static MercSpell GetBestMercSpellForHate(Merc* caster);
|
||||
bool UseDiscipline(int32 spell_id, int32 target);
|
||||
|
||||
virtual bool IsMerc() const { return true; }
|
||||
|
||||
virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
|
||||
static Merc* LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id);
|
||||
void UpdateMercStats(Client *c);
|
||||
void UpdateMercAppearance(Client *c);
|
||||
static const char *GetRandomName();
|
||||
bool Spawn(Client *owner);
|
||||
bool Dismiss();
|
||||
bool Suspend();
|
||||
bool Unsuspend();
|
||||
void Zone();
|
||||
virtual void Depop();
|
||||
bool GetDepop() { return p_depop; }
|
||||
|
||||
bool IsDead() { return GetHP() < 0;};
|
||||
bool IsMedding() {return _medding; };
|
||||
bool IsSuspended() {return _suspended; };
|
||||
|
||||
static uint32 CalcPurchaseCost( uint32 templateID , uint8 level, uint8 currency_type = 0);
|
||||
static uint32 CalcUpkeepCost( uint32 templateID , uint8 level, uint8 currency_type = 0);
|
||||
|
||||
// "GET" Class Methods
|
||||
virtual Mob* GetOwner();
|
||||
Client* GetMercOwner();
|
||||
virtual Mob* GetOwnerOrSelf();
|
||||
uint32 GetMercID() { return _MercID; }
|
||||
uint32 GetMercCharacterID( ) { return owner_char_id; }
|
||||
uint32 GetMercTemplateID() { return _MercTemplateID; }
|
||||
uint32 GetMercType() { return _MercType; }
|
||||
uint32 GetMercSubType() { return _MercSubType; }
|
||||
uint32 GetProficiencyID() { return _ProficiencyID; }
|
||||
uint32 GetCostFormula() { return _CostFormula; }
|
||||
uint32 GetMercNameType() { return _NameType; }
|
||||
uint32 GetStance() { return _currentStance; }
|
||||
|
||||
inline const uint8 GetClientVersion() const { return _OwnerClientVersion; }
|
||||
|
||||
virtual void SetTarget(Mob* mob);
|
||||
bool HasSkill(SkillType skill_id) const;
|
||||
bool CanHaveSkill(SkillType skill_id) const;
|
||||
uint16 MaxSkill(SkillType skillid, uint16 class_, uint16 level) const;
|
||||
inline uint16 MaxSkill(SkillType skillid) const { return MaxSkill(skillid, GetClass(), GetLevel()); }
|
||||
virtual void DoClassAttacks(Mob *target);
|
||||
bool CheckTaunt();
|
||||
bool CheckAETaunt();
|
||||
|
||||
// stat functions
|
||||
virtual void CalcBonuses();
|
||||
inline virtual int16 GetAC() const { return AC; }
|
||||
inline virtual int16 GetATK() const { return ATK; }
|
||||
inline virtual int16 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; }
|
||||
int GetRawACNoShield(int &shield_ac) const;
|
||||
|
||||
inline virtual int16 GetSTR() const { return STR; }
|
||||
inline virtual int16 GetSTA() const { return STA; }
|
||||
inline virtual int16 GetDEX() const { return DEX; }
|
||||
inline virtual int16 GetAGI() const { return AGI; }
|
||||
inline virtual int16 GetINT() const { return INT; }
|
||||
inline virtual int16 GetWIS() const { return WIS; }
|
||||
inline virtual int16 GetCHA() const { return CHA; }
|
||||
inline virtual int16 GetMR() const { return MR; }
|
||||
inline virtual int16 GetFR() const { return FR; }
|
||||
inline virtual int16 GetDR() const { return DR; }
|
||||
inline virtual int16 GetPR() const { return PR; }
|
||||
inline virtual int16 GetCR() const { return CR; }
|
||||
inline virtual int16 GetCorrup() const { return Corrup; }
|
||||
|
||||
inline virtual int16 GetHeroicSTR() const { return itembonuses.HeroicSTR; }
|
||||
inline virtual int16 GetHeroicSTA() const { return itembonuses.HeroicSTA; }
|
||||
inline virtual int16 GetHeroicDEX() const { return itembonuses.HeroicDEX; }
|
||||
inline virtual int16 GetHeroicAGI() const { return itembonuses.HeroicAGI; }
|
||||
inline virtual int16 GetHeroicINT() const { return itembonuses.HeroicINT; }
|
||||
inline virtual int16 GetHeroicWIS() const { return itembonuses.HeroicWIS; }
|
||||
inline virtual int16 GetHeroicCHA() const { return itembonuses.HeroicCHA; }
|
||||
inline virtual int16 GetHeroicMR() const { return itembonuses.HeroicMR; }
|
||||
inline virtual int16 GetHeroicFR() const { return itembonuses.HeroicFR; }
|
||||
inline virtual int16 GetHeroicDR() const { return itembonuses.HeroicDR; }
|
||||
inline virtual int16 GetHeroicPR() const { return itembonuses.HeroicPR; }
|
||||
inline virtual int16 GetHeroicCR() const { return itembonuses.HeroicCR; }
|
||||
inline virtual int16 GetHeroicCorrup() const { return itembonuses.HeroicCorrup; }
|
||||
// Mod2
|
||||
inline virtual int16 GetShielding() const { return itembonuses.MeleeMitigation; }
|
||||
inline virtual int16 GetSpellShield() const { return itembonuses.SpellShield; }
|
||||
inline virtual int16 GetDoTShield() const { return itembonuses.DoTShielding; }
|
||||
inline virtual int16 GetStunResist() const { return itembonuses.StunResist; }
|
||||
inline virtual int16 GetStrikeThrough() const { return itembonuses.StrikeThrough; }
|
||||
inline virtual int16 GetAvoidance() const { return itembonuses.AvoidMeleeChance; }
|
||||
inline virtual int16 GetAccuracy() const { return itembonuses.HitChance; }
|
||||
inline virtual int16 GetCombatEffects() const { return itembonuses.ProcChance; }
|
||||
inline virtual int16 GetDS() const { return itembonuses.DamageShield; }
|
||||
// Mod3
|
||||
inline virtual int16 GetHealAmt() const { return itembonuses.HealAmt; }
|
||||
inline virtual int16 GetSpellDmg() const { return itembonuses.SpellDmg; }
|
||||
inline virtual int16 GetClair() const { return itembonuses.Clairvoyance; }
|
||||
inline virtual int16 GetDSMit() const { return itembonuses.DSMitigation; }
|
||||
|
||||
inline virtual int16 GetSingMod() const { return itembonuses.singingMod; }
|
||||
inline virtual int16 GetBrassMod() const { return itembonuses.brassMod; }
|
||||
inline virtual int16 GetPercMod() const { return itembonuses.percussionMod; }
|
||||
inline virtual int16 GetStringMod() const { return itembonuses.stringedMod; }
|
||||
inline virtual int16 GetWindMod() const { return itembonuses.windMod; }
|
||||
|
||||
inline virtual int16 GetDelayDeath() const { return aabonuses.DelayDeath + spellbonuses.DelayDeath + itembonuses.DelayDeath + 11; }
|
||||
|
||||
// "SET" Class Methods
|
||||
void SetMercData (uint32 templateID );
|
||||
void SetMercID( uint32 mercID ) { _MercID = mercID; }
|
||||
void SetMercCharacterID( uint32 mercID ) { owner_char_id = mercID; }
|
||||
void SetMercTemplateID( uint32 templateID ) { _MercTemplateID = templateID; }
|
||||
void SetMercType( uint32 type ) { _MercType = type; }
|
||||
void SetMercSubType( uint32 subtype ) { _MercSubType = subtype; }
|
||||
void SetProficiencyID( uint8 proficiency_id ) { _ProficiencyID = proficiency_id; }
|
||||
void SetCostFormula( uint8 costformula ) { _CostFormula = costformula; }
|
||||
void SetMercNameType( uint8 nametype ) { _NameType = nametype; }
|
||||
void SetClientVersion(uint8 clientVersion) { _OwnerClientVersion = clientVersion; }
|
||||
void SetSuspended(bool suspended) { _suspended = suspended; }
|
||||
void SetStance( uint32 stance ) { _currentStance = stance; }
|
||||
|
||||
void Sit();
|
||||
void Stand();
|
||||
bool IsSitting();
|
||||
bool IsStanding();
|
||||
|
||||
// Merc-specific functions
|
||||
bool IsMercCaster() { return (GetClass() == CLERIC || GetClass() == DRUID || GetClass() == SHAMAN || GetClass() == NECROMANCER || GetClass() == WIZARD || GetClass() == MAGICIAN || GetClass() == ENCHANTER); }
|
||||
bool IsMercCasterCombatRange(Mob *target);
|
||||
virtual float GetMaxMeleeRangeToTarget(Mob* target);
|
||||
virtual void MercMeditate(bool isSitting);
|
||||
bool FindTarget();
|
||||
|
||||
protected:
|
||||
void CalcItemBonuses(StatBonuses* newbon);
|
||||
void AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug = false, bool isTribute = false);
|
||||
int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat);
|
||||
|
||||
std::vector<MercSpell> merc_spells;
|
||||
std::map<uint32,MercTimer> timers;
|
||||
|
||||
uint16 skills[HIGHEST_SKILL+1];
|
||||
uint32 equipment[MAX_WORN_INVENTORY]; //this is an array of item IDs
|
||||
uint16 d_meele_texture1; //this is an item Material value
|
||||
uint16 d_meele_texture2; //this is an item Material value (offhand)
|
||||
uint8 prim_melee_type; //Sets the Primary Weapon attack message and animation
|
||||
uint8 sec_melee_type; //Sets the Secondary Weapon attack message and animation
|
||||
|
||||
private:
|
||||
|
||||
int16 CalcAC();
|
||||
int16 GetACMit();
|
||||
int16 GetACAvoid();
|
||||
int16 acmod();
|
||||
int16 CalcATK();
|
||||
//int CalcHaste();
|
||||
|
||||
int16 CalcSTR();
|
||||
int16 CalcSTA();
|
||||
int16 CalcDEX();
|
||||
int16 CalcAGI();
|
||||
int16 CalcINT();
|
||||
int16 CalcWIS();
|
||||
int16 CalcCHA();
|
||||
|
||||
int16 CalcMR();
|
||||
int16 CalcFR();
|
||||
int16 CalcDR();
|
||||
int16 CalcPR();
|
||||
int16 CalcCR();
|
||||
int16 CalcCorrup();
|
||||
int32 CalcMaxHP();
|
||||
int32 CalcBaseHP();
|
||||
int32 GetClassHPFactor();
|
||||
int32 CalcHPRegen();
|
||||
int32 CalcHPRegenCap();
|
||||
int32 CalcMaxMana();
|
||||
int32 CalcBaseMana();
|
||||
int32 CalcManaRegen();
|
||||
int32 CalcBaseManaRegen();
|
||||
int32 CalcManaRegenCap();
|
||||
void CalcMaxEndurance(); //This calculates the maximum endurance we can have
|
||||
int32 CalcBaseEndurance(); //Calculates Base End
|
||||
int32 GetEndurance() const {return cur_end;} //This gets our current endurance
|
||||
int32 GetMaxEndurance() const {return max_end;} //This gets our endurance from the last CalcMaxEndurance() call
|
||||
int32 CalcEnduranceRegen(); //Calculates endurance regen used in DoEnduranceRegen()
|
||||
int32 CalcEnduranceRegenCap();
|
||||
void SetEndurance(int32 newEnd); //This sets the current endurance to the new value
|
||||
void DoEnduranceUpkeep(); //does the endurance upkeep
|
||||
void CalcRestState();
|
||||
|
||||
int GroupLeadershipAAHealthEnhancement();
|
||||
int GroupLeadershipAAManaEnhancement();
|
||||
int GroupLeadershipAAHealthRegeneration();
|
||||
int GroupLeadershipAAOffenseEnhancement();
|
||||
|
||||
void GenerateBaseStats();
|
||||
void GenerateAppearance();
|
||||
|
||||
bool LoadMercSpells();
|
||||
bool CheckStance(int16 stance);
|
||||
std::vector<MercSpell> GetMercSpells() { return merc_spells; }
|
||||
|
||||
// Private "base stats" Members
|
||||
int32 base_mana;
|
||||
int _baseAC;
|
||||
uint16 _baseSTR;
|
||||
uint16 _baseSTA;
|
||||
uint16 _baseDEX;
|
||||
uint16 _baseAGI;
|
||||
uint16 _baseINT;
|
||||
uint16 _baseWIS;
|
||||
uint16 _baseCHA;
|
||||
uint16 _baseATK;
|
||||
uint16 _baseRace; // Necessary to preserve the race otherwise mercs get their race updated in the db when they get an illusion.
|
||||
uint8 _baseGender; // Merc gender. Necessary to preserve the original value otherwise it can be changed by illusions.
|
||||
uint16 _baseMR;
|
||||
uint16 _baseCR;
|
||||
uint16 _baseDR;
|
||||
uint16 _baseFR;
|
||||
uint16 _basePR;
|
||||
uint16 _baseCorrup;
|
||||
uint32 RestRegenHP;
|
||||
uint32 RestRegenMana;
|
||||
uint32 RestRegenEndurance;
|
||||
|
||||
uint32 _MercID;
|
||||
uint32 _MercTemplateID;
|
||||
uint32 _MercType;
|
||||
uint32 _MercSubType;
|
||||
uint8 _ProficiencyID;
|
||||
uint8 _CostFormula;
|
||||
uint8 _NameType;
|
||||
uint8 _OwnerClientVersion;
|
||||
uint32 _currentStance;
|
||||
|
||||
Inventory m_inv;
|
||||
int32 max_end;
|
||||
int32 cur_end;
|
||||
bool _medding;
|
||||
bool _suspended;
|
||||
bool p_depop;
|
||||
uint32 owner_char_id;
|
||||
const NPCType* ourNPCData;
|
||||
|
||||
Timer endupkeep_timer;
|
||||
Timer rest_timer;
|
||||
};
|
||||
|
||||
#endif // MERC_H
|
||||
@@ -0,0 +1,7 @@
|
||||
struct Msg {
|
||||
int id;
|
||||
char* Sender;
|
||||
char* Subject;
|
||||
char* Body;
|
||||
char* Date;
|
||||
};
|
||||
+4479
File diff suppressed because it is too large
Load Diff
+1120
File diff suppressed because it is too large
Load Diff
+1385
File diff suppressed because it is too large
Load Diff
+61
@@ -0,0 +1,61 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifdef _WINDOWS
|
||||
#include <windows.h>
|
||||
#include <winsock.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include "../common/types.h"
|
||||
#include "../common/timer.h"
|
||||
void CatchSignal(int);
|
||||
void UpdateWindowTitle(char* iNewTitle = 0);
|
||||
|
||||
class NetConnection
|
||||
{
|
||||
public:
|
||||
~NetConnection();
|
||||
NetConnection();
|
||||
|
||||
uint32 GetIP();
|
||||
uint32 GetIP(char* name);
|
||||
void SaveInfo(char* address, uint32 port, char* waddress,char* filename);
|
||||
char* GetWorldAddress() { return WorldAddress; }
|
||||
char* GetZoneAddress() { return ZoneAddress; }
|
||||
char* GetZoneFileName() { return ZoneFileName; }
|
||||
uint32 GetZonePort() { return ZonePort; }
|
||||
Timer object_timer;
|
||||
Timer door_timer;
|
||||
Timer corpse_timer;
|
||||
Timer group_timer;
|
||||
Timer raid_timer;
|
||||
Timer trap_timer;
|
||||
private:
|
||||
uint16 ZonePort;
|
||||
char* ZoneAddress;
|
||||
char* WorldAddress;
|
||||
char ZoneFileName[50];
|
||||
};
|
||||
+2350
File diff suppressed because it is too large
Load Diff
+562
@@ -0,0 +1,562 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef NPC_H
|
||||
#define NPC_H
|
||||
|
||||
class NPC;
|
||||
#include "zonedb.h"
|
||||
#include "mob.h"
|
||||
//#include "spawn.h"
|
||||
|
||||
#include <list>
|
||||
#include <deque>
|
||||
using namespace std;
|
||||
|
||||
#include "spawn2.h"
|
||||
#include "loottable.h"
|
||||
#include "zonedump.h"
|
||||
#include "QGlobals.h"
|
||||
#include "../common/rulesys.h"
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#define M_PI 3.141592
|
||||
#endif
|
||||
|
||||
#define LEAVECOMBAT 0
|
||||
#define ENTERCOMBAT 1
|
||||
#define ONDEATH 2
|
||||
#define AFTERDEATH 3
|
||||
#define HAILED 4
|
||||
#define KILLEDPC 5
|
||||
#define KILLEDNPC 6
|
||||
#define ONSPAWN 7
|
||||
#define ONDESPAWN 8
|
||||
|
||||
typedef struct {
|
||||
float min_x;
|
||||
float max_x;
|
||||
float min_y;
|
||||
float max_y;
|
||||
float min_z;
|
||||
float max_z;
|
||||
bool say;
|
||||
} NPCProximity;
|
||||
|
||||
struct AISpells_Struct {
|
||||
uint16 type; // 0 = never, must be one (and only one) of the defined values
|
||||
uint16 spellid; // <= 0 = no spell
|
||||
int16 manacost; // -1 = use spdat, -2 = no cast time
|
||||
uint32 time_cancast; // when we can cast this spell next
|
||||
int32 recast_delay;
|
||||
int16 priority;
|
||||
int16 resist_adjust;
|
||||
};
|
||||
|
||||
class AA_SwarmPetInfo;
|
||||
|
||||
class NPC : public Mob
|
||||
{
|
||||
public:
|
||||
static NPC* SpawnNPC(const char* spawncommand, float in_x, float in_y, float in_z, float in_heading = 0, Client* client = 0);
|
||||
static int8 GetAILevel(bool iForceReRead = false);
|
||||
|
||||
NPC(const NPCType* data, Spawn2* respawn, float x, float y, float z, float heading, int iflymode, bool IsCorpse = false);
|
||||
|
||||
virtual ~NPC();
|
||||
|
||||
//abstract virtual function implementations requird by base abstract class
|
||||
virtual void Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillType attack_skill);
|
||||
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false);
|
||||
virtual bool Attack(Mob* other, int Hand = 13, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false);
|
||||
virtual bool HasRaid() { return false; }
|
||||
virtual bool HasGroup() { return false; }
|
||||
virtual Raid* GetRaid() { return 0; }
|
||||
virtual Group* GetGroup() { return 0; }
|
||||
|
||||
virtual bool IsNPC() const { return true; }
|
||||
|
||||
virtual bool Process();
|
||||
virtual void AI_Init();
|
||||
virtual void AI_Start(uint32 iMoveDelay = 0);
|
||||
virtual void AI_Stop();
|
||||
void AI_DoMovement();
|
||||
bool AI_AddNPCSpells(uint32 iDBSpellsID);
|
||||
virtual bool AI_EngagedCastCheck();
|
||||
bool AI_HasSpells() { return HasAISpell; }
|
||||
|
||||
virtual bool AI_PursueCastCheck();
|
||||
virtual bool AI_IdleCastCheck();
|
||||
virtual void AI_Event_SpellCastFinished(bool iCastSucceeded, uint8 slot);
|
||||
|
||||
void LevelScale();
|
||||
void CalcNPCResists();
|
||||
void CalcNPCRegen();
|
||||
void CalcNPCDamage();
|
||||
|
||||
|
||||
int32 GetActSpellDamage(uint16 spell_id, int32 value);
|
||||
int32 GetActSpellHealing(uint16 spell_id, int32 value);
|
||||
inline void SetSpellFocusDMG(int32 NewSpellFocusDMG) {SpellFocusDMG = NewSpellFocusDMG;}
|
||||
inline void SetSpellFocusHeal(int32 NewSpellFocusHeal) {SpellFocusHeal = NewSpellFocusHeal;}
|
||||
int32 SpellFocusDMG;
|
||||
int32 SpellFocusHeal;
|
||||
|
||||
virtual void SetTarget(Mob* mob);
|
||||
virtual uint16 GetSkill(SkillType skill_num) const { if (skill_num <= HIGHEST_SKILL) { return skills[skill_num]; } return 0; }
|
||||
|
||||
void CalcItemBonuses(StatBonuses *newbon);
|
||||
virtual void CalcBonuses();
|
||||
virtual int GetCurrentBuffSlots() const { return RuleI(Spells, MaxBuffSlotsNPC); }
|
||||
virtual int GetCurrentSongSlots() const { return RuleI(Spells, MaxSongSlotsNPC); }
|
||||
virtual int GetCurrentDiscSlots() const { return RuleI(Spells, MaxDiscSlotsNPC); }
|
||||
virtual int GetMaxBuffSlots() const { return RuleI(Spells, MaxBuffSlotsNPC); }
|
||||
virtual int GetMaxSongSlots() const { return RuleI(Spells, MaxSongSlotsNPC); }
|
||||
virtual int GetMaxDiscSlots() const { return RuleI(Spells, MaxDiscSlotsNPC); }
|
||||
virtual int GetMaxTotalSlots() const { return RuleI(Spells, MaxTotalSlotsNPC); }
|
||||
virtual int GetPetMaxTotalSlots() const { return RuleI(Spells, MaxTotalSlotsPET); }
|
||||
virtual void InitializeBuffSlots();
|
||||
virtual void UninitializeBuffSlots();
|
||||
|
||||
virtual void RangedAttack(Mob* other);
|
||||
virtual void ThrowingAttack(Mob* other) { }
|
||||
int32 GetNumberOfAttacks() const { return attack_count; }
|
||||
|
||||
bool DatabaseCastAccepted(int spell_id);
|
||||
bool IsFactionListAlly(uint32 other_faction);
|
||||
FACTION_VALUE CheckNPCFactionAlly(int32 other_faction);
|
||||
virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther);
|
||||
|
||||
void GoToBind(uint8 bindnum = 0) { GMMove(org_x, org_y, org_z, org_heading); }
|
||||
void Gate();
|
||||
|
||||
void GetPetState(SpellBuff_Struct *buffs, uint32 *items, char *name);
|
||||
void SetPetState(SpellBuff_Struct *buffs, uint32 *items);
|
||||
void InteractiveChat(uint8 chan_num, uint8 language, const char * message, const char* targetname,Mob* sender);
|
||||
void TakenAction(uint8 action,Mob* actiontaker);
|
||||
virtual void SpellProcess();
|
||||
virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
|
||||
|
||||
void AddItem(const Item_Struct* item, uint16 charges, bool equipitem = true);
|
||||
void AddItem(uint32 itemid, uint16 charges, bool equipitem = true);
|
||||
void AddLootTable();
|
||||
|
||||
void DescribeAggro(Client *towho, Mob *mob, bool verbose);
|
||||
void RemoveItem(uint32 item_id, uint16 quantity = 0, uint16 slot = 0);
|
||||
void CheckMinMaxLevel(Mob *them);
|
||||
void ClearItemList();
|
||||
ServerLootItem_Struct* GetItem(int slot_id);
|
||||
void AddCash(uint16 in_copper, uint16 in_silver, uint16 in_gold, uint16 in_platinum);
|
||||
void AddCash();
|
||||
void RemoveCash();
|
||||
void QueryLoot(Client* to);
|
||||
uint32 CountLoot();
|
||||
void DumpLoot(uint32 npcdump_index, ZSDump_NPC_Loot* npclootdump, uint32* NPCLootindex);
|
||||
inline uint32 GetLoottableID() const { return loottable_id; }
|
||||
|
||||
inline uint32 GetCopper() const { return copper; }
|
||||
inline uint32 GetSilver() const { return silver; }
|
||||
inline uint32 GetGold() const { return gold; }
|
||||
inline uint32 GetPlatinum() const { return platinum; }
|
||||
|
||||
inline void SetCopper(uint32 amt) { copper = amt; }
|
||||
inline void SetSilver(uint32 amt) { silver = amt; }
|
||||
inline void SetGold(uint32 amt) { gold = amt; }
|
||||
inline void SetPlatinum(uint32 amt) { platinum = amt; }
|
||||
|
||||
|
||||
virtual int32 CalcMaxMana();
|
||||
void SetGrid(int32 grid_){ grid=grid_; }
|
||||
void SetSp2(uint32 sg2){ spawn_group=sg2; }
|
||||
void SetWaypointMax(uint16 wp_){ wp_m=wp_; }
|
||||
void SetSaveWaypoint(uint16 wp_){ save_wp=wp_; }
|
||||
|
||||
uint16 GetWaypointMax() const { return wp_m; }
|
||||
int32 GetGrid() const { return grid; }
|
||||
uint32 GetSp2() const { return spawn_group; }
|
||||
uint32 GetSpawnPointID() const;
|
||||
|
||||
float GetSpawnPointX() const { return org_x; }
|
||||
float GetSpawnPointY() const { return org_y; }
|
||||
float GetSpawnPointZ() const { return org_z; }
|
||||
float GetSpawnPointH() const { return org_heading; }
|
||||
float GetGuardPointX() const { return guard_x; }
|
||||
float GetGuardPointY() const { return guard_y; }
|
||||
float GetGuardPointZ() const { return guard_z; }
|
||||
float GetGuardPointH() const { return guard_heading; }
|
||||
EmuAppearance GetGuardPointAnim() const { return guard_anim; }
|
||||
void SaveGuardPointAnim(EmuAppearance anim) { guard_anim = anim; }
|
||||
|
||||
void SetFlyMode(uint8 FlyMode){ flymode=FlyMode; }
|
||||
uint32 GetFlyMode() const { return flymode; }
|
||||
|
||||
uint8 GetPrimSkill() const { return prim_melee_type; }
|
||||
uint8 GetSecSkill() const { return sec_melee_type; }
|
||||
void SetPrimSkill(uint8 skill_type) { prim_melee_type = skill_type; }
|
||||
void SetSecSkill(uint8 skill_type) { sec_melee_type = skill_type; }
|
||||
|
||||
uint32 MerchantType;
|
||||
void Depop(bool StartSpawnTimer = false);
|
||||
void Stun(int duration);
|
||||
void UnStun();
|
||||
uint32 GetSwarmOwner();
|
||||
uint32 GetSwarmTarget();
|
||||
void SetSwarmTarget(int target_id = 0);
|
||||
|
||||
void SignalNPC(int _signal_id);
|
||||
|
||||
inline int32 GetNPCFactionID() const { return npc_faction_id; }
|
||||
inline int32 GetPrimaryFaction() const { return primary_faction; }
|
||||
int32 GetNPCHate(Mob* in_ent) {return hate_list.GetEntHate(in_ent);}
|
||||
bool IsOnHatelist(Mob*p) { return hate_list.IsOnHateList(p);}
|
||||
|
||||
void SetNPCFactionID(int32 in) { npc_faction_id = in; database.GetFactionIdsForNPC(npc_faction_id, &faction_list, &primary_faction); }
|
||||
|
||||
float org_x, org_y, org_z, org_heading;
|
||||
|
||||
uint32 GetMaxDMG() const {return max_dmg;}
|
||||
uint32 GetMinDMG() const {return min_dmg;}
|
||||
float GetSlowMitigation() const {return slow_mitigation;}
|
||||
float GetAttackSpeed() const {return attack_speed;}
|
||||
bool IsAnimal() const { return(bodytype == BT_Animal); }
|
||||
uint16 GetPetSpellID() const {return pet_spell_id;}
|
||||
void SetPetSpellID(uint16 amt) {pet_spell_id = amt;}
|
||||
uint32 GetMaxDamage(uint8 tlevel);
|
||||
void SetTaunting(bool tog) {taunting = tog;}
|
||||
void PickPocket(Client* thief);
|
||||
void StartSwarmTimer(uint32 duration) { swarm_timer.Start(duration); }
|
||||
void AddLootDrop(const Item_Struct*dbitem, ItemList* itemlistconst, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange = false);
|
||||
virtual void DoClassAttacks(Mob *target);
|
||||
void CheckSignal();
|
||||
|
||||
//waypoint crap
|
||||
int GetMaxWp() const { return max_wp; }
|
||||
void DisplayWaypointInfo(Client *to);
|
||||
void CalculateNewWaypoint();
|
||||
void AssignWaypoints(int32 grid);
|
||||
void SetWaypointPause();
|
||||
void UpdateWaypoint(int wp_index);
|
||||
|
||||
// quest wandering commands
|
||||
void StopWandering();
|
||||
void ResumeWandering();
|
||||
void PauseWandering(int pausetime);
|
||||
void MoveTo(float mtx, float mty, float mtz, float mth, bool saveguardspot);
|
||||
void GetClosestWaypoint(list<wplist> &wp_list, int count, float m_x, float m_y, float m_z);
|
||||
|
||||
uint32 GetEquipment(uint8 material_slot) const; // returns item id
|
||||
int32 GetEquipmentMaterial(uint8 material_slot) const;
|
||||
|
||||
void NextGuardPosition();
|
||||
void SaveGuardSpot(bool iClearGuardSpot = false);
|
||||
inline bool IsGuarding() const { return(guard_heading != 0); }
|
||||
void SaveGuardSpotCharm();
|
||||
void RestoreGuardSpotCharm();
|
||||
void AI_SetRoambox(float iDist, float iRoamDist, uint32 iDelay = 2500);
|
||||
void AI_SetRoambox(float iDist, float iMaxX, float iMinX, float iMaxY, float iMinY, uint32 iDelay = 2500);
|
||||
|
||||
//mercenary stuff
|
||||
void LoadMercTypes();
|
||||
void LoadMercs();
|
||||
std::list<MercType> GetMercTypesList() {return mercTypeList; };
|
||||
std::list<MercType> GetMercTypesList( uint32 expansion );
|
||||
std::list<MercData> GetMercsList() {return mercDataList; };
|
||||
std::list<MercData> GetMercsList( uint32 expansion );
|
||||
int GetNumMercTypes() { return static_cast<int>(mercTypeList.size()); };
|
||||
int GetNumMercTypes( uint32 expansion );
|
||||
int GetNumMercs() { return static_cast<int>(mercDataList.size()); };
|
||||
int GetNumMercs( uint32 expansion );
|
||||
|
||||
inline bool WillAggroNPCs() const { return(npc_aggro); }
|
||||
|
||||
inline void GiveNPCTypeData(NPCType *ours) { NPCTypedata_ours = ours; }
|
||||
inline const uint32 GetNPCSpellsID() const { return npc_spells_id; }
|
||||
|
||||
ItemList itemlist; //kathgar - why is this public? Doing other things or I would check the code
|
||||
|
||||
NPCProximity* proximity;
|
||||
Spawn2* respawn2;
|
||||
QGlobalCache *GetQGlobals() { return qGlobals; }
|
||||
QGlobalCache *CreateQGlobals() { qGlobals = new QGlobalCache(); return qGlobals; }
|
||||
|
||||
AA_SwarmPetInfo *GetSwarmInfo() { return (swarmInfoPtr); }
|
||||
void SetSwarmInfo(AA_SwarmPetInfo *mSwarmInfo) { swarmInfoPtr = mSwarmInfo; }
|
||||
|
||||
int32 GetAccuracyRating() const { return (accuracy_rating); }
|
||||
void SetAccuracyRating(int32 d) { accuracy_rating = d;}
|
||||
int32 GetRawAC() const { return AC; }
|
||||
|
||||
void ModifyNPCStat(const char *identifier, const char *newValue);
|
||||
virtual void SetLevel(uint8 in_level, bool command = false);
|
||||
|
||||
bool IsLDoNTrapped() const { return (ldon_trapped); }
|
||||
void SetLDoNTrapped(bool n) { ldon_trapped = n; }
|
||||
|
||||
uint8 GetLDoNTrapType() const { return (ldon_trap_type); }
|
||||
void SetLDoNTrapType(uint8 n) { ldon_trap_type = n; }
|
||||
|
||||
uint16 GetLDoNTrapSpellID() const { return (ldon_spell_id); }
|
||||
void SetLDoNTrapSpellID(uint16 n) { ldon_spell_id = n; }
|
||||
|
||||
bool IsLDoNLocked() const { return (ldon_locked); }
|
||||
void SetLDoNLocked(bool n) { ldon_locked = n; }
|
||||
|
||||
uint16 GetLDoNLockedSkill() const { return (ldon_locked_skill); }
|
||||
void SetLDoNLockedSkill(uint16 n) { ldon_locked_skill = n; }
|
||||
|
||||
bool IsLDoNTrapDetected() const { return (ldon_trap_detected); }
|
||||
void SetLDoNTrapDetected(bool n) { ldon_trap_detected = n; }
|
||||
|
||||
const bool GetCombatEvent() const { return combat_event; }
|
||||
void SetCombatEvent(bool b) { combat_event = b; }
|
||||
|
||||
//The corpse we make can only be looted by people who got credit for the kill
|
||||
const bool HasPrivateCorpse() const { return NPCTypedata->private_corpse; }
|
||||
const bool IsUnderwaterOnly() const { return NPCTypedata->underwater; }
|
||||
const uint32 GetNPCEmoteID() const { return NPCTypedata->emoteid; }
|
||||
const char* GetRawNPCTypeName() const { return NPCTypedata->name; }
|
||||
|
||||
bool GetDepop() { return p_depop; }
|
||||
|
||||
void NPCSlotTexture(uint8 slot, uint16 texture); // Sets new material values for slots
|
||||
|
||||
uint32 GetAdventureTemplate() const { return adventure_template_id; }
|
||||
void AddSpellToNPCList(int16 iPriority, int16 iSpellID, uint16 iType, int16 iManaCost, int32 iRecastDelay, int16 iResistAdjust);
|
||||
void RemoveSpellFromNPCList(int16 spell_id);
|
||||
Timer *GetRefaceTimer() const { return reface_timer; }
|
||||
const uint32 GetAltCurrencyType() const { return NPCTypedata->alt_currency_type; }
|
||||
|
||||
NPC_Emote_Struct* GetNPCEmote(uint16 emoteid, uint8 event_);
|
||||
void DoNPCEmote(uint8 event_, uint16 emoteid);
|
||||
bool CanTalk();
|
||||
|
||||
inline void SetSpellScale(float amt) { spellscale = amt; }
|
||||
inline float GetSpellScale() { return spellscale; }
|
||||
|
||||
inline void SetHealScale(float amt) { healscale = amt; }
|
||||
inline float GetHealScale() { return healscale; }
|
||||
|
||||
void AddQuestItem(ItemInst* inst) { questItems.Insert(inst); }
|
||||
|
||||
void ClearQuestLists()
|
||||
{
|
||||
ClearQuestItems(true);
|
||||
ClearQuestDeleteItems(true);
|
||||
}
|
||||
|
||||
void ResetQuestDeleteList()
|
||||
{
|
||||
ClearQuestDeleteItems(true);
|
||||
}
|
||||
|
||||
|
||||
void ClearQuestItems(bool delete_=false)
|
||||
{
|
||||
LinkedListIterator<ItemInst*> iterator(questItems);
|
||||
iterator.Reset();
|
||||
while(iterator.MoreElements())
|
||||
{
|
||||
iterator.RemoveCurrent(delete_);
|
||||
}
|
||||
|
||||
questItems.Clear();
|
||||
}
|
||||
|
||||
void ClearQuestDeleteItems(bool delete_=false)
|
||||
{
|
||||
LinkedListIterator<ItemInst*> iterator(questDeletionItems);
|
||||
iterator.Reset();
|
||||
while(iterator.MoreElements())
|
||||
{
|
||||
iterator.RemoveCurrent(delete_);
|
||||
}
|
||||
|
||||
questDeletionItems.Clear();
|
||||
}
|
||||
|
||||
ItemInst* FindQuestItemByID(uint32 itmID, int charges, bool flagItemForDeletion=false)
|
||||
{
|
||||
LinkedListIterator<ItemInst*> iterator(questItems);
|
||||
iterator.Reset();
|
||||
int totalCharges = 0;
|
||||
while(iterator.MoreElements())
|
||||
{
|
||||
if ( iterator.GetData()->GetItem()->ID == itmID )
|
||||
{
|
||||
totalCharges += 1;
|
||||
|
||||
if ( flagItemForDeletion )
|
||||
questDeletionItems.Insert(iterator.GetData()->Clone());
|
||||
if ( charges > totalCharges )
|
||||
{
|
||||
iterator.Advance();
|
||||
continue;
|
||||
}
|
||||
|
||||
return iterator.GetData();
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool DoesQuestItemExist(uint32 itmID, int charges, bool flagItemForDeletion=false) {
|
||||
ItemInst* inst = FindQuestItemByID(itmID,charges,flagItemForDeletion);
|
||||
if ( inst != NULL )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void ClearQuestItem(ItemInst* inst, bool delete_=true)
|
||||
{
|
||||
LinkedListIterator<ItemInst*> iterator(questItems);
|
||||
iterator.Reset();
|
||||
|
||||
while(iterator.MoreElements())
|
||||
{
|
||||
if ( iterator.GetData ()->GetItem()->ID == inst->GetItem()->ID )
|
||||
{
|
||||
iterator.RemoveCurrent(delete_);
|
||||
break;
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveQuestDeleteItems()
|
||||
{
|
||||
LinkedListIterator<ItemInst*> iterator(questDeletionItems);
|
||||
iterator.Reset();
|
||||
while(iterator.MoreElements())
|
||||
{
|
||||
ClearQuestItem(iterator.GetData(),true);
|
||||
iterator.RemoveCurrent(true);
|
||||
}
|
||||
|
||||
questDeletionItems.Clear();
|
||||
}
|
||||
|
||||
void PrintOutQuestItems(Client* c);
|
||||
|
||||
protected:
|
||||
|
||||
const NPCType* NPCTypedata;
|
||||
NPCType* NPCTypedata_ours; //special case for npcs with uniquely created data.
|
||||
|
||||
friend class EntityList;
|
||||
list<struct NPCFaction*> faction_list;
|
||||
uint32 copper;
|
||||
uint32 silver;
|
||||
uint32 gold;
|
||||
uint32 platinum;
|
||||
int32 grid;
|
||||
uint32 spawn_group;
|
||||
uint16 wp_m;
|
||||
|
||||
int32 npc_faction_id;
|
||||
int32 primary_faction;
|
||||
|
||||
Timer attacked_timer; //running while we are being attacked (damaged)
|
||||
Timer swarm_timer;
|
||||
Timer classattack_timer;
|
||||
Timer knightattack_timer;
|
||||
Timer assist_timer; //ask for help from nearby mobs
|
||||
Timer qglobal_purge_timer;
|
||||
|
||||
bool combat_event; //true if we are in combat, false otherwise
|
||||
Timer sendhpupdate_timer;
|
||||
Timer enraged_timer;
|
||||
Timer *reface_timer;
|
||||
|
||||
uint32 npc_spells_id;
|
||||
uint8 casting_spell_AIindex;
|
||||
Timer* AIautocastspell_timer;
|
||||
uint32* pDontCastBefore_casting_spell;
|
||||
std::vector<AISpells_Struct> AIspells;
|
||||
bool HasAISpell;
|
||||
virtual bool AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes);
|
||||
virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0);
|
||||
|
||||
|
||||
uint32 max_dmg;
|
||||
uint32 min_dmg;
|
||||
int32 accuracy_rating;
|
||||
int16 attack_count;
|
||||
uint32 npc_mana;
|
||||
float spellscale;
|
||||
float healscale;
|
||||
|
||||
//pet crap:
|
||||
uint16 pet_spell_id;
|
||||
bool taunting;
|
||||
Timer taunt_timer; //for pet taunting
|
||||
|
||||
bool npc_aggro;
|
||||
|
||||
deque<int> signal_q;
|
||||
|
||||
//waypoint crap:
|
||||
vector<wplist> Waypoints;
|
||||
void _ClearWaypints();
|
||||
int max_wp;
|
||||
int save_wp;
|
||||
float guard_x, guard_y, guard_z, guard_heading;
|
||||
float guard_x_saved, guard_y_saved, guard_z_saved, guard_heading_saved;
|
||||
EmuAppearance guard_anim;
|
||||
float roambox_max_x;
|
||||
float roambox_max_y;
|
||||
float roambox_min_x;
|
||||
float roambox_min_y;
|
||||
float roambox_distance;
|
||||
float roambox_movingto_x;
|
||||
float roambox_movingto_y;
|
||||
uint32 roambox_delay;
|
||||
|
||||
uint16 skills[HIGHEST_SKILL+1];
|
||||
uint32 equipment[MAX_WORN_INVENTORY]; //this is an array of item IDs
|
||||
uint16 d_meele_texture1; //this is an item Material value
|
||||
uint16 d_meele_texture2; //this is an item Material value (offhand)
|
||||
uint8 prim_melee_type; //Sets the Primary Weapon attack message and animation
|
||||
uint8 sec_melee_type; //Sets the Secondary Weapon attack message and animation
|
||||
AA_SwarmPetInfo *swarmInfoPtr;
|
||||
|
||||
bool ldon_trapped;
|
||||
uint8 ldon_trap_type;
|
||||
uint16 ldon_spell_id;
|
||||
bool ldon_locked;
|
||||
uint16 ldon_locked_skill;
|
||||
bool ldon_trap_detected;
|
||||
QGlobalCache *qGlobals;
|
||||
uint32 adventure_template_id;
|
||||
|
||||
LinkedList<ItemInst*> questItems;
|
||||
LinkedList<ItemInst*> questDeletionItems;
|
||||
|
||||
//mercenary stuff
|
||||
std::list<MercType> mercTypeList;
|
||||
std::list<MercData> mercDataList;
|
||||
|
||||
private:
|
||||
uint32 loottable_id;
|
||||
bool p_depop;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+231
@@ -0,0 +1,231 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef OBJECT_H
|
||||
#define OBJECT_H
|
||||
|
||||
// Object Class:
|
||||
// Represents Zone Objects (forges, ovens, brew barrels, items dropped to ground, etc)
|
||||
|
||||
#include "../common/types.h"
|
||||
#include "../common/linked_list.h"
|
||||
#include "../common/emu_opcodes.h"
|
||||
#include "../common/eq_packet_structs.h"
|
||||
#include "../common/Item.h"
|
||||
#include "client.h"
|
||||
#include "mob.h"
|
||||
#include "npc.h"
|
||||
#include "entity.h"
|
||||
#include "../common/timer.h"
|
||||
|
||||
/*
|
||||
item icon numbers (showeq)
|
||||
IT1_ACTORDEF=Long Sword
|
||||
IT5_ACTORDEF=Throwing Knife
|
||||
IT8_ACTORDEF=Basic Staff
|
||||
IT10_ACTORDEF=Arrow
|
||||
IT14_ACTORDEF=Basic Hammer
|
||||
IT16_ACTORDEF=Basic Spear
|
||||
IT27_ACTORDEF=Book
|
||||
IT35_ACTORDEF=Mod Rod
|
||||
IT62_ACTORDEF=Flaming Sword
|
||||
IT63_ACTORDEF=Small Bag
|
||||
IT64_ACTORDEF=Large Bag
|
||||
IT65_ACTORDEF=Scroll
|
||||
IT66_ACTORDEF=Forge
|
||||
IT67_ACTORDEF=Voodoo Doll
|
||||
IT68_ACTORDEF=Glowing Black Stone
|
||||
IT69_ACTORDEF=Oven
|
||||
IT70_ACTORDEF=Brew Barrel
|
||||
IT73_ACTORDEF=Kiln
|
||||
IT74_ACTORDEF=Pottery Wheel
|
||||
IT78_ACTORDEF=Campfire (Oven)
|
||||
IT128_ACTORDEF=Loom
|
||||
IT177_ACTORDEF=Shattering Hammer
|
||||
IT203_ACTORDEF=Round Shield
|
||||
IT210_ACTORDEF=Shimmering Orb
|
||||
IT400_ACTORDEF=Globe of Slush Water
|
||||
IT401_ACTORDEF=Red Mushroom
|
||||
IT402_ACTORDEF=Blue Mushroom
|
||||
IT403_ACTORDEF=Yew Leaf
|
||||
IT10511_ACTORDEF=A Soulstone Shard
|
||||
IT10512_ACTORDEF=Orb of Exploration
|
||||
IT10630_ACTORDEF=Fish Sword
|
||||
IT10661_ACTORDEF=Blade of Walnan
|
||||
IT10714_ACTORDEF=Augmentation Sealer
|
||||
IT10725_ACTORDEF=Shuriken
|
||||
*/
|
||||
|
||||
// Object Types
|
||||
#define OT_DROPPEDITEM 0x01
|
||||
#define OT_MEDICINEBAG 0x09
|
||||
#define OT_TOOLBOX 0x0A
|
||||
#define OT_OVEN 0x0F
|
||||
#define OT_SEWINGKIT 0x10 //and loom
|
||||
#define OT_FORGE 0x11
|
||||
#define OT_FLETCHINGKIT 0x12
|
||||
#define OT_BREWBARREL 0x13
|
||||
#define OT_JEWELERSKIT 0x14
|
||||
#define OT_POTTERYWHEEL 0x15
|
||||
#define OT_KILN 0x16
|
||||
#define OT_KEYMAKER 0x17
|
||||
#define OT_WIZARDLEX 0x18
|
||||
#define OT_MAGELEX 0x19
|
||||
#define OT_NECROLEX 0x1A
|
||||
#define OT_ENCHLEX 0x1B
|
||||
// high elf forge is 0x1F (Koada'dal forge)
|
||||
#define OT_TEIRDALFORGE 0x20 //dark elf
|
||||
#define OT_OGGOKFORGE 0x21 //ogre
|
||||
#define OT_STORMGUARDF 0x22 //dwarven
|
||||
#define OT_VALEFORGE 0x31 //halfling
|
||||
// gnome forge 0x23 (ak'anon forge)
|
||||
// barbarian forge 0x24 (northman forge)
|
||||
//
|
||||
// iksar forge 0x26 (cabilis forge)
|
||||
// human forge 0x27 (qeynos or freeport?) (royal qeynos forge or freeport forge)
|
||||
// human forge 0x28 (qeynos or freeport?)
|
||||
// halfling tailoring kit 0x29
|
||||
// erudite tailoring kit 0x2A
|
||||
// wood elf tailoring kit 0x2B
|
||||
// wood elf fletching kit 0x2C
|
||||
// iksar pottery wheel 0x2D
|
||||
#define OT_TACKLEBOX 0x2e
|
||||
// troll forge 0x2F (grobb forge)
|
||||
#define OT_FIERDALFFORGE 0x30
|
||||
// erudite forge 0x32 (erud forge)
|
||||
#define OT_AUGMENT 0x35
|
||||
//... (shar vahl forge)
|
||||
//... wood elf (fier'dal forge)
|
||||
//... (froglok forge)
|
||||
|
||||
// Icon values:
|
||||
//0x0453 a pie
|
||||
//0x0454 cookies?
|
||||
//0x0455 is a piece of meat?
|
||||
//0x0456 is fletching sticks
|
||||
//0x0457 looks like a burnt cookie or something :/
|
||||
//0x0458 is a pottery wheel
|
||||
//0x0459 is a oven
|
||||
//0x045A is an oven
|
||||
//0x045B is a forge
|
||||
//0x045C is brewing barrel
|
||||
//0x045D is a hammer
|
||||
//0x045E is a wierd rope shape
|
||||
|
||||
class Object: public Entity
|
||||
{
|
||||
public:
|
||||
// Loading object from database
|
||||
Object(uint32 id, uint32 type, uint32 icon, const Object_Struct& data, const ItemInst* inst);
|
||||
Object(const ItemInst* inst, char* name,float max_x,float min_x,float max_y,float min_y,float z,float heading,uint32 respawntimer);
|
||||
// Loading object from client dropping item on ground
|
||||
Object(Client* client, const ItemInst* inst);
|
||||
Object(const ItemInst *inst, float x, float y, float z, float heading, uint32 decay_time = 300000);
|
||||
Object(const char *model, float x, float y, float z, float heading, uint8 type, uint32 decay_time = 0);
|
||||
|
||||
// Destructor
|
||||
~Object();
|
||||
bool Process();
|
||||
bool IsGroundSpawn() { return m_ground_spawn; }
|
||||
// Event handlers
|
||||
bool HandleClick(Client* sender, const ClickObject_Struct* click_object);
|
||||
void Close();
|
||||
void Delete(bool reset_state=false); // Object itself
|
||||
static void HandleCombine(Client* user, const NewCombine_Struct* in_combine, Object *worldo);
|
||||
static void HandleAugmentation(Client* user, const AugmentItem_Struct* in_augment, Object *worldo);
|
||||
static void HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac);
|
||||
|
||||
static SkillType TypeToSkill(uint32 type);
|
||||
|
||||
// Packet functions
|
||||
void CreateSpawnPacket(EQApplicationPacket* app);
|
||||
void CreateDeSpawnPacket(EQApplicationPacket* app);
|
||||
void Depop();
|
||||
void Repop();
|
||||
|
||||
//Decay functions
|
||||
void StartDecay() {decay_timer.Start();}
|
||||
|
||||
// Container functions
|
||||
void PutItem(uint8 index, const ItemInst* inst);
|
||||
void DeleteItem(uint8 index); // Item inside container
|
||||
ItemInst* PopItem(uint8 index); // Pop item out of container
|
||||
|
||||
// Override base class implementations
|
||||
virtual bool IsObject() const { return true; }
|
||||
virtual bool Save();
|
||||
virtual uint16 VarSave();
|
||||
virtual void SetID(uint16 set_id);
|
||||
|
||||
void ClearUser() { user = NULL; }
|
||||
|
||||
uint32 GetDBID();
|
||||
uint32 GetType();
|
||||
void SetType(uint32 type);
|
||||
void SetDBID(uint32 dbid);
|
||||
uint32 GetIcon();
|
||||
void SetIcon(uint32 icon);
|
||||
uint32 GetItemID();
|
||||
void SetItemID(uint32 itemid);
|
||||
void GetObjectData(Object_Struct* Data);
|
||||
void SetObjectData(Object_Struct* Data);
|
||||
void GetLocation(float* x, float* y, float* z);
|
||||
void SetLocation(float x, float y, float z);
|
||||
void GetHeading(float* heading);
|
||||
void SetHeading(float heading);
|
||||
float GetX();
|
||||
float GetY();
|
||||
float GetZ();
|
||||
float GetHeadingData();
|
||||
void SetX(float pos);
|
||||
void SetY(float pos);
|
||||
void SetZ(float pos);
|
||||
void SetModelName(const char* modelname);
|
||||
const char* GetModelName();
|
||||
|
||||
const char* GetEntityVariable(const char *id);
|
||||
void SetEntityVariable(const char *id, const char *m_var);
|
||||
bool EntityVariableExists(const char *id);
|
||||
|
||||
protected:
|
||||
void ResetState(); // Set state back to original
|
||||
void RandomSpawn(bool send_packet = false); //spawn this ground spawn at a random place
|
||||
|
||||
Object_Struct m_data; // Packet data
|
||||
ItemInst* m_inst; // Item representing object
|
||||
bool m_inuse; // Currently in use by a client?
|
||||
uint32 m_id; // Database key, different than drop_id
|
||||
uint32 m_type; // Object Type, ie, forge, oven, dropped item, etc
|
||||
uint32 m_icon; // Icon to use for forge, oven, etc
|
||||
float m_max_x;
|
||||
float m_max_y;
|
||||
float m_min_x;
|
||||
float m_min_y;
|
||||
float m_z;
|
||||
float m_heading;
|
||||
bool m_ground_spawn;
|
||||
|
||||
std::map<std::string, std::string> o_EntityVariables;
|
||||
|
||||
Client *user;
|
||||
Client *last_user;
|
||||
|
||||
Timer respawn_timer;
|
||||
Timer decay_timer;
|
||||
};
|
||||
|
||||
#endif
|
||||
+1859
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,25 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2004 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef OLDCODE_H
|
||||
#define OLDCODE_H
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
+1698
File diff suppressed because it is too large
Load Diff
+124
@@ -0,0 +1,124 @@
|
||||
#ifndef PARSER_H
|
||||
#define PARSER_H
|
||||
|
||||
#define Parser_MaxVars 1024
|
||||
#include "../common/timer.h"
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include "event_codes.h"
|
||||
#include "QuestInterface.h"
|
||||
|
||||
|
||||
struct EventList {
|
||||
std::string event;
|
||||
std::string command;
|
||||
};
|
||||
|
||||
struct Events {
|
||||
uint32 npcid;
|
||||
std::list<EventList*> Event;
|
||||
};
|
||||
|
||||
struct Alias {
|
||||
int index;
|
||||
uint32 npcid;
|
||||
char name[100][100];
|
||||
char command[100][1024];
|
||||
};
|
||||
|
||||
struct vars {
|
||||
std::string name;
|
||||
std::string value;
|
||||
};
|
||||
|
||||
struct command_list {
|
||||
char command_name[100];
|
||||
int param_amount[17];
|
||||
};
|
||||
|
||||
|
||||
class Parser : public QuestInterface
|
||||
{
|
||||
public:
|
||||
Parser();
|
||||
virtual ~Parser();
|
||||
int mindex;
|
||||
const std::string DEFAULT_QUEST_PREFIX;
|
||||
|
||||
typedef list<Events*>::iterator iter_events;
|
||||
typedef list<EventList*>::iterator iter_eventlist;
|
||||
std::list<Events*> MainList;
|
||||
std::list<vars*> varlist;
|
||||
std::list<Alias*> AliasList;
|
||||
uint32 npcarrayindex;
|
||||
|
||||
uint32 AddNPCQuestID(uint32 npcid);
|
||||
uint32 FindNPCQuestID(int32 npcid);
|
||||
int CheckAliases(const char * alias, uint32 npcid, Mob* npcmob, Mob* mob);
|
||||
void ClearAliasesByNPCID(uint32 iNPCID);
|
||||
void ClearCache();
|
||||
void ClearEventsByNPCID(uint32 iNPCID);
|
||||
|
||||
void DelChatAndItemVars(uint32 npcid);
|
||||
void DeleteVar(std::string name);
|
||||
|
||||
void ExCommands(std::string command, std::string parms, int argnums, uint32 npcid, Mob* other, Mob* mob );
|
||||
|
||||
void GetCommandName(char * command1, char * arg);
|
||||
int GetFreeID();
|
||||
int GetItemCount(std::string itemid, uint32 npcid);
|
||||
int32 GetNPCqstID(uint32 iNPCID);
|
||||
std::string GetVar(std::string varname, uint32 npcid);
|
||||
|
||||
void HandleVars(std::string varname, std::string varparms, std::string& origstring, std::string format, uint32 npcid, Mob* mob);
|
||||
|
||||
bool LoadAttempted(uint32 iNPCID);
|
||||
void LoadCommands(const char * filename);
|
||||
virtual int LoadScript(int npcid, const char * zone, Mob* activater=0);
|
||||
|
||||
void MakeParms(const char * string, uint32 npcid);
|
||||
void MakeVars(std::string text, uint32 npcid);
|
||||
|
||||
int numtok(const char *text, char character);
|
||||
|
||||
int ParseCommands(std::string text, int line, int justcheck, uint32 npcid, Mob* other, Mob* mob, std::string filename=string("none"));
|
||||
int ParseIf(std::string text);
|
||||
int pcalc(const char * string);
|
||||
void ParseVars(std::string& text, uint32 npcid, Mob* mob);
|
||||
|
||||
void Replace(std::string& string1, std::string repstr, std::string rep, int all=0);
|
||||
|
||||
void scanformat(char *string, const char *format, char arg[10][1024]);
|
||||
bool SetNPCqstID(uint32 iNPCID, int32 iValue);
|
||||
char * strrstr(char* string, const char * sub);
|
||||
virtual void SendCommands(const char * event, uint32 npcid, NPC* npcmob, Mob* mob);
|
||||
|
||||
int HasQuestFile(uint32 npcid);
|
||||
|
||||
//interface stuff
|
||||
virtual void EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data) {}
|
||||
virtual void EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data) {}
|
||||
virtual void EventGlobalPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data) {}
|
||||
virtual void EventItem(QuestEventID evt, Client *client, ItemInst *item, uint32 objid, uint32 extra_data) {}
|
||||
virtual void EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data) {}
|
||||
virtual bool HasQuestSub(uint32 npcid, const char *subname) { return HasQuestFile(npcid) != 0; }
|
||||
virtual bool PlayerHasQuestSub(const char *subname) { return true; }
|
||||
virtual bool GlobalPlayerHasQuestSub(const char *subname) { return true; }
|
||||
virtual bool SpellHasQuestSub(uint32 spell_id, const char *subname) { return true; }
|
||||
virtual bool ItemHasQuestSub(ItemInst *itm, const char *subname) { return true; }
|
||||
virtual void AddVar(std::string varname, std::string varval);
|
||||
virtual void ReloadQuests(bool with_timers = false);
|
||||
virtual uint32 GetIdentifier() { return 0x04629fff; }
|
||||
|
||||
private:
|
||||
//void Event(int event, uint32 npcid, const char * data, Mob* npcmob, Mob* mob);
|
||||
//changed - Eglin. more reasonable (IMHO) than changing every single referance to the global pointer.
|
||||
//that's what you get for using globals! :)
|
||||
virtual void Event(QuestEventID event, uint32 npcid, const char * data, NPC* npcmob, Mob* mob, uint32 extradata = 0);
|
||||
|
||||
uint32 pMaxNPCID;
|
||||
int32* pNPCqstID;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+2297
File diff suppressed because it is too large
Load Diff
+112
@@ -0,0 +1,112 @@
|
||||
#ifndef PATHING_H
|
||||
#define PATHING_H
|
||||
#include <algorithm>
|
||||
#include "map.h"
|
||||
#include "../common/timer.h"
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class Client;
|
||||
|
||||
#define PATHNODENEIGHBOURS 50
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
struct AStarNode
|
||||
{
|
||||
int PathNodeID;
|
||||
int Parent;
|
||||
float HCost;
|
||||
float GCost;
|
||||
bool Teleport;
|
||||
};
|
||||
|
||||
struct NeighbourNode {
|
||||
int16 id;
|
||||
float distance;
|
||||
uint8 Teleport;
|
||||
int16 DoorID;
|
||||
};
|
||||
|
||||
struct PathNode {
|
||||
uint16 id;
|
||||
VERTEX v;
|
||||
float bestz;
|
||||
NeighbourNode Neighbours[PATHNODENEIGHBOURS];
|
||||
};
|
||||
|
||||
struct PathFileHeader {
|
||||
uint32 version;
|
||||
uint32 PathNodeCount;
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
struct PathNodeSortStruct
|
||||
{
|
||||
int id;
|
||||
float Distance;
|
||||
};
|
||||
|
||||
enum LOSType{ UnknownLOS, HaveLOS, NoLOS };
|
||||
|
||||
class PathManager {
|
||||
|
||||
public:
|
||||
PathManager();
|
||||
~PathManager();
|
||||
|
||||
|
||||
static PathManager *LoadPathFile(const char *ZoneName);
|
||||
bool loadPaths(FILE *fp);
|
||||
void PrintPathing();
|
||||
list<int> FindRoute(VERTEX Start, VERTEX End);
|
||||
list<int> FindRoute(int startID, int endID);
|
||||
|
||||
VERTEX GetPathNodeCoordinates(int NodeNumber, bool BestZ = true);
|
||||
bool CheckLosFN(VERTEX a, VERTEX b);
|
||||
void SpawnPathNodes();
|
||||
void MeshTest();
|
||||
void SimpleMeshTest();
|
||||
int FindNearestPathNode(VERTEX Position);
|
||||
bool NoHazards(VERTEX From, VERTEX To);
|
||||
bool NoHazardsAccurate(VERTEX From, VERTEX To);
|
||||
void OpenDoors(int Node1, int Node2, Mob* ForWho);
|
||||
|
||||
PathNode* FindPathNodeByCoordinates(float x, float y, float z);
|
||||
void ShowPathNodeNeighbours(Client *c);
|
||||
int GetRandomPathNode();
|
||||
|
||||
void NodeInfo(Client *c);
|
||||
int32 AddNode(float x, float y, float z, float best_z, int32 requested_id = 0); //return -1 on failure, else returns the id of this node
|
||||
bool DeleteNode(Client *c);
|
||||
bool DeleteNode(int32 id); //returns true on success, false on failure, tries to delete a node from this map
|
||||
void ConnectNodeToNode(Client *c, int32 Node2, int32 teleport = 0, int32 doorid = -1); //connects a node both ways
|
||||
void ConnectNodeToNode(int32 Node1, int32 Node2, int32 teleport = 0, int32 doorid = -1);
|
||||
void ConnectNode(Client *c, int32 Node2, int32 teleport = 0, int32 doorid = -1); //connects a node one way
|
||||
void ConnectNode(int32 Node1, int32 Node2, int32 teleport = 0, int32 doorid = -1);
|
||||
void DisconnectNodeToNode(Client *c, int32 Node2);
|
||||
void DisconnectNodeToNode(int32 Node1, int32 Node2);
|
||||
void MoveNode(Client *c);
|
||||
void DisconnectAll(Client *c);
|
||||
bool NodesConnected(PathNode *a, PathNode *b);
|
||||
void DumpPath(string filename);
|
||||
void ProcessNodesAndSave(string filename);
|
||||
void ResortConnections();
|
||||
void QuickConnect(Client *c, bool set = false);
|
||||
void SortNodes();
|
||||
|
||||
private:
|
||||
PathFileHeader Head;
|
||||
PathNode *PathNodes;
|
||||
int QuickConnectTarget;
|
||||
|
||||
int *ClosedListFlag;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,839 @@
|
||||
/*
|
||||
* This file was generated automatically by xsubpp version 1.9508 from the
|
||||
* contents of tmp. Do not edit this file, edit tmp instead.
|
||||
*
|
||||
* ANY CHANGES MADE HERE WILL BE LOST!
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "features.h"
|
||||
#ifdef EMBPERL_XS_CLASSES
|
||||
#include "../common/debug.h"
|
||||
#include "embperl.h"
|
||||
|
||||
#include "PlayerCorpse.h"
|
||||
|
||||
#ifdef THIS /* this macro seems to leak out on some systems */
|
||||
#undef THIS
|
||||
#endif
|
||||
|
||||
|
||||
XS(XS_Corpse_GetCharID); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_GetCharID)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::GetCharID(THIS)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
uint32 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetCharID();
|
||||
XSprePUSH; PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Corpse_GetDecayTime); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_GetDecayTime)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::GetDecayTime(THIS)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
uint32 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetDecayTime();
|
||||
XSprePUSH; PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Corpse_Lock); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_Lock)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::Lock(THIS)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->Lock();
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Corpse_UnLock); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_UnLock)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::UnLock(THIS)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->UnLock();
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Corpse_IsLocked); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_IsLocked)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::IsLocked(THIS)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
bool RETVAL;
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->IsLocked();
|
||||
ST(0) = boolSV(RETVAL);
|
||||
sv_2mortal(ST(0));
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Corpse_ResetLooter); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_ResetLooter)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::ResetLooter(THIS)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->ResetLooter();
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Corpse_GetDBID); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_GetDBID)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::GetDBID(THIS)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
uint32 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetDBID();
|
||||
XSprePUSH; PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Corpse_GetOwnerName); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_GetOwnerName)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::GetOwnerName(THIS)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
char * RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetOwnerName();
|
||||
sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG;
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Corpse_SetDecayTimer); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_SetDecayTimer)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::SetDecayTimer(THIS, decaytime)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
uint32 decaytime = (uint32)SvUV(ST(1));
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->SetDecayTimer(decaytime);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Corpse_IsEmpty); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_IsEmpty)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::IsEmpty(THIS)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
bool RETVAL;
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->IsEmpty();
|
||||
ST(0) = boolSV(RETVAL);
|
||||
sv_2mortal(ST(0));
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Corpse_AddItem); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_AddItem)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items < 3 || items > 4)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::AddItem(THIS, itemnum, charges, slot= 0)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
uint32 itemnum = (uint32)SvUV(ST(1));
|
||||
uint16 charges = (uint16)SvUV(ST(2));
|
||||
int16 slot;
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
if (items < 4)
|
||||
slot = 0;
|
||||
else {
|
||||
slot = (int16)SvIV(ST(3));
|
||||
}
|
||||
|
||||
THIS->AddItem(itemnum, charges, slot);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Corpse_GetWornItem); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_GetWornItem)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::GetWornItem(THIS, equipSlot)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
uint32 RETVAL;
|
||||
dXSTARG;
|
||||
int16 equipSlot = (int16)SvIV(ST(1));
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetWornItem(equipSlot);
|
||||
XSprePUSH; PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Corpse_RemoveItem); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_RemoveItem)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::RemoveItem(THIS, lootslot)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
uint16 lootslot = (uint16)SvUV(ST(1));
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->RemoveItem(lootslot);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Corpse_SetCash); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_SetCash)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 5)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::SetCash(THIS, in_copper, in_silver, in_gold, in_platinum)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
uint16 in_copper = (uint16)SvUV(ST(1));
|
||||
uint16 in_silver = (uint16)SvUV(ST(2));
|
||||
uint16 in_gold = (uint16)SvUV(ST(3));
|
||||
uint16 in_platinum = (uint16)SvUV(ST(4));
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->SetCash(in_copper, in_silver, in_gold, in_platinum);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Corpse_RemoveCash); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_RemoveCash)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::RemoveCash(THIS)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->RemoveCash();
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Corpse_CountItems); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_CountItems)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::CountItems(THIS)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
uint32 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->CountItems();
|
||||
XSprePUSH; PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Corpse_Delete); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_Delete)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::Delete(THIS)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->Delete();
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Corpse_GetCopper); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_GetCopper)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::GetCopper(THIS)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
uint32 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetCopper();
|
||||
XSprePUSH; PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Corpse_GetSilver); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_GetSilver)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::GetSilver(THIS)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
uint32 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetSilver();
|
||||
XSprePUSH; PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Corpse_GetGold); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_GetGold)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::GetGold(THIS)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
uint32 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetGold();
|
||||
XSprePUSH; PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Corpse_GetPlatinum); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_GetPlatinum)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::GetPlatinum(THIS)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
uint32 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetPlatinum();
|
||||
XSprePUSH; PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Corpse_Summon); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_Summon)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 3)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::Summon(THIS, client, spell)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
Client* client;
|
||||
bool spell = (bool)SvTRUE(ST(2));
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
if (sv_derived_from(ST(1), "Client")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(1)));
|
||||
client = INT2PTR(Client *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "client is not of type Client");
|
||||
if(client == NULL)
|
||||
Perl_croak(aTHX_ "client is NULL, avoiding crash.");
|
||||
|
||||
THIS->Summon(client, spell, true);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Corpse_CastRezz); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_CastRezz)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 3)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::CastRezz(THIS, spellid, Caster)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
uint16 spellid = (uint16)SvUV(ST(1));
|
||||
Mob* Caster;
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
if (sv_derived_from(ST(2), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(2)));
|
||||
Caster = INT2PTR(Mob *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "Caster is not of type Mob");
|
||||
if(Caster == NULL)
|
||||
Perl_croak(aTHX_ "Caster is NULL, avoiding crash.");
|
||||
|
||||
THIS->CastRezz(spellid, Caster);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Corpse_CompleteRezz); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_CompleteRezz)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::CompleteRezz(THIS)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->CompleteRezz();
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Corpse_CanMobLoot); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_CanMobLoot)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::CanMobLoot(THIS, charid)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
bool RETVAL;
|
||||
int charid = (int)SvIV(ST(1));
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->CanMobLoot(charid);
|
||||
ST(0) = boolSV(RETVAL);
|
||||
sv_2mortal(ST(0));
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Corpse_AllowMobLoot); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_AllowMobLoot)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 3)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::AllowMobLoot(THIS, them, slot)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
Mob * them;
|
||||
uint8 slot = (uint8)SvUV(ST(2));
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
if (sv_derived_from(ST(1), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(1)));
|
||||
them = INT2PTR(Mob *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "them is not of type Mob");
|
||||
if(them == NULL)
|
||||
Perl_croak(aTHX_ "them is NULL, avoiding crash.");
|
||||
|
||||
THIS->AllowMobLoot(them, slot);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Corpse_AddLooter); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_AddLooter)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::AddLooter(THIS, who)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
Mob * who;
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
if (sv_derived_from(ST(1), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(1)));
|
||||
who = INT2PTR(Mob *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "who is not of type Mob");
|
||||
if(who == NULL)
|
||||
Perl_croak(aTHX_ "who is NULL, avoiding crash.");
|
||||
|
||||
THIS->AddLooter(who);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Corpse_IsRezzed); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_IsRezzed)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::IsRezzed(THIS)");
|
||||
{
|
||||
Corpse * THIS;
|
||||
bool RETVAL;
|
||||
|
||||
if (sv_derived_from(ST(0), "Corpse")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Corpse *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Corpse");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->Rezzed();
|
||||
ST(0) = boolSV(RETVAL);
|
||||
sv_2mortal(ST(0));
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
XS(boot_Corpse); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(boot_Corpse)
|
||||
{
|
||||
dXSARGS;
|
||||
char file[256];
|
||||
strncpy(file, __FILE__, 256);
|
||||
file[255] = 0;
|
||||
|
||||
if(items != 1)
|
||||
fprintf(stderr, "boot_quest does not take any arguments.");
|
||||
char buf[128];
|
||||
|
||||
//add the strcpy stuff to get rid of const warnings....
|
||||
|
||||
|
||||
|
||||
XS_VERSION_BOOTCHECK ;
|
||||
|
||||
newXSproto(strcpy(buf, "GetCharID"), XS_Corpse_GetCharID, file, "$");
|
||||
newXSproto(strcpy(buf, "GetDecayTime"), XS_Corpse_GetDecayTime, file, "$");
|
||||
newXSproto(strcpy(buf, "Lock"), XS_Corpse_Lock, file, "$");
|
||||
newXSproto(strcpy(buf, "UnLock"), XS_Corpse_UnLock, file, "$");
|
||||
newXSproto(strcpy(buf, "IsLocked"), XS_Corpse_IsLocked, file, "$");
|
||||
newXSproto(strcpy(buf, "ResetLooter"), XS_Corpse_ResetLooter, file, "$");
|
||||
newXSproto(strcpy(buf, "GetDBID"), XS_Corpse_GetDBID, file, "$");
|
||||
newXSproto(strcpy(buf, "GetOwnerName"), XS_Corpse_GetOwnerName, file, "$");
|
||||
newXSproto(strcpy(buf, "SetDecayTimer"), XS_Corpse_SetDecayTimer, file, "$$");
|
||||
newXSproto(strcpy(buf, "IsEmpty"), XS_Corpse_IsEmpty, file, "$");
|
||||
newXSproto(strcpy(buf, "AddItem"), XS_Corpse_AddItem, file, "$$$;$");
|
||||
newXSproto(strcpy(buf, "GetWornItem"), XS_Corpse_GetWornItem, file, "$$");
|
||||
newXSproto(strcpy(buf, "RemoveItem"), XS_Corpse_RemoveItem, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetCash"), XS_Corpse_SetCash, file, "$$$$$");
|
||||
newXSproto(strcpy(buf, "RemoveCash"), XS_Corpse_RemoveCash, file, "$");
|
||||
newXSproto(strcpy(buf, "CountItems"), XS_Corpse_CountItems, file, "$");
|
||||
newXSproto(strcpy(buf, "Delete"), XS_Corpse_Delete, file, "$");
|
||||
newXSproto(strcpy(buf, "GetCopper"), XS_Corpse_GetCopper, file, "$");
|
||||
newXSproto(strcpy(buf, "GetSilver"), XS_Corpse_GetSilver, file, "$");
|
||||
newXSproto(strcpy(buf, "GetGold"), XS_Corpse_GetGold, file, "$");
|
||||
newXSproto(strcpy(buf, "GetPlatinum"), XS_Corpse_GetPlatinum, file, "$");
|
||||
newXSproto(strcpy(buf, "Summon"), XS_Corpse_Summon, file, "$$$");
|
||||
newXSproto(strcpy(buf, "CastRezz"), XS_Corpse_CastRezz, file, "$$$");
|
||||
newXSproto(strcpy(buf, "CompleteRezz"), XS_Corpse_CompleteRezz, file, "$");
|
||||
newXSproto(strcpy(buf, "CanMobLoot"), XS_Corpse_CanMobLoot, file, "$$");
|
||||
newXSproto(strcpy(buf, "AllowMobLoot"), XS_Corpse_AllowMobLoot, file, "$$$");
|
||||
newXSproto(strcpy(buf, "AddLooter"), XS_Corpse_AddLooter, file, "$$");
|
||||
newXSproto(strcpy(buf, "IsRezzed"), XS_Corpse_IsRezzed, file, "$");
|
||||
XSRETURN_YES;
|
||||
}
|
||||
|
||||
#endif //EMBPERL_XS_CLASSES
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,768 @@
|
||||
/*
|
||||
* This file was generated automatically by xsubpp version 1.9508 from the
|
||||
* contents of tmp. Do not edit this file, edit tmp instead.
|
||||
*
|
||||
* ANY CHANGES MADE HERE WILL BE LOST!
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "features.h"
|
||||
#ifdef EMBPERL_XS_CLASSES
|
||||
#include "../common/debug.h"
|
||||
#include "embperl.h"
|
||||
|
||||
#include "doors.h"
|
||||
|
||||
#ifdef THIS /* this macro seems to leak out on some systems */
|
||||
#undef THIS
|
||||
#endif
|
||||
|
||||
XS(XS_Doors_GetDoorDBID); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_GetDoorDBID)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Doors::GetDoorDBID(THIS)");
|
||||
{
|
||||
Doors * THIS;
|
||||
uint32 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetDoorDBID();
|
||||
XSprePUSH; PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Doors_GetDoorID); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_GetDoorID)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Doors::GetDoorID(THIS)");
|
||||
{
|
||||
Doors * THIS;
|
||||
uint32 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetDoorID();
|
||||
XSprePUSH; PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Doors_GetID); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_GetID)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Doors::GetID(THIS)");
|
||||
{
|
||||
Doors * THIS;
|
||||
uint16 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetEntityID();
|
||||
XSprePUSH; PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Doors_GetX); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_GetX)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Doors::GetX(THIS)");
|
||||
{
|
||||
Doors * THIS;
|
||||
float RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetX();
|
||||
XSprePUSH; PUSHn((double)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Doors_GetY); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_GetY)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Doors::GetY(THIS)");
|
||||
{
|
||||
Doors * THIS;
|
||||
float RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetY();
|
||||
XSprePUSH; PUSHn((double)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Doors_GetZ); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_GetZ)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Doors::GetZ(THIS)");
|
||||
{
|
||||
Doors * THIS;
|
||||
float RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetZ();
|
||||
XSprePUSH; PUSHn((double)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Doors_GetHeading); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_GetHeading)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Doors::GetHeading(THIS)");
|
||||
{
|
||||
Doors * THIS;
|
||||
float RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetHeading();
|
||||
XSprePUSH; PUSHn((double)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Doors_GetOpenType); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_GetOpenType)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Doors::GetOpenType(THIS)");
|
||||
{
|
||||
Doors * THIS;
|
||||
uint32 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetOpenType();
|
||||
XSprePUSH; PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Doors_GetLockpick); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_GetLockpick)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Doors::GetLockpick(THIS)");
|
||||
{
|
||||
Doors * THIS;
|
||||
uint32 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetLockpick();
|
||||
XSprePUSH; PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Doors_GetKeyItem); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_GetKeyItem)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Doors::GetKeyItem(THIS)");
|
||||
{
|
||||
Doors * THIS;
|
||||
uint32 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetKeyItem();
|
||||
XSprePUSH; PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Doors_GetNoKeyring); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_GetNoKeyring)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Doors::GetNoKeyring(THIS, type)");
|
||||
{
|
||||
Doors * THIS;
|
||||
uint8 type = (uint8)SvUV(ST(1));
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->GetNoKeyring();
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Doors_GetIncline); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_GetIncline)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Doors::GetIncline(THIS)");
|
||||
{
|
||||
Doors * THIS;
|
||||
uint32 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetIncline();
|
||||
XSprePUSH; PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Doors_GetSize); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_GetSize)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Doors::GetIncline(THIS)");
|
||||
{
|
||||
Doors * THIS;
|
||||
uint32 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetSize();
|
||||
XSprePUSH; PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
XS(XS_Doors_SetOpenType); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_SetOpenType)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Doors::SetOpenType(THIS, type)");
|
||||
{
|
||||
Doors * THIS;
|
||||
uint32 type = (uint32)SvUV(ST(1));
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->SetOpenType(type);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Doors_SetLockpick); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_SetLockpick)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Doors::SetLockpick(THIS, type)");
|
||||
{
|
||||
Doors * THIS;
|
||||
uint32 type = (uint32)SvUV(ST(1));
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->SetLockpick(type);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Doors_SetKeyItem); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_SetKeyItem)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Doors::SetKeyItem(THIS, type)");
|
||||
{
|
||||
Doors * THIS;
|
||||
uint32 type = (uint32)SvUV(ST(1));
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->SetKeyItem(type);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Doors_SetNoKeyring); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_SetNoKeyring)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Doors::SetNoKeyring(THIS, type)");
|
||||
{
|
||||
Doors * THIS;
|
||||
uint8 type = (uint8)SvUV(ST(1));
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->SetNoKeyring(type);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Doors_SetIncline); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_SetIncline)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Doors::SetIncline(THIS, type)");
|
||||
{
|
||||
Doors * THIS;
|
||||
uint32 type = (uint32)SvUV(ST(1));
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->SetIncline(type);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Doors_SetSize); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_SetSize)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Doors::SetSize(THIS, size)");
|
||||
{
|
||||
Doors * THIS;
|
||||
uint32 type = (uint32)SvUV(ST(1));
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->SetSize(type);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Doors_SetLocation); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_SetLocation)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 4)
|
||||
Perl_croak(aTHX_ "Usage: Doors::SetLocation(THIS, x, y, z)");
|
||||
{
|
||||
Doors * THIS;
|
||||
float x = (float)SvNV(ST(1));
|
||||
float y = (float)SvNV(ST(2));
|
||||
float z = (float)SvNV(ST(3));
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->SetLocation(x, y, z);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Doors_SetX); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_SetX)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Doors::SetX(THIS, XPos)");
|
||||
{
|
||||
Doors * THIS;
|
||||
float pos = (float)SvNV(ST(1));
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->SetX(pos);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Doors_SetY); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_SetY)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Doors::SetY(THIS, YPos)");
|
||||
{
|
||||
Doors * THIS;
|
||||
float pos = (float)SvNV(ST(1));
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->SetY(pos);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Doors_SetZ); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_SetZ)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Doors::SetZ(THIS, ZPos)");
|
||||
{
|
||||
Doors * THIS;
|
||||
float pos = (float)SvNV(ST(1));
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->SetZ(pos);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Doors_SetHeading); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_SetHeading)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Doors::SetHeading(THIS, heading)");
|
||||
{
|
||||
Doors * THIS;
|
||||
float heading = (float)SvNV(ST(1));
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->SetHeading(heading);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Doors_SetModelName); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_SetModelName)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items < 1 || items > 2)
|
||||
Perl_croak(aTHX_ "Usage: Doors::SetModelName(THIS, name)");
|
||||
{
|
||||
Doors * THIS;
|
||||
char * name = NULL;
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
if (items > 1) { name = (char *)SvPV_nolen(ST(1)); }
|
||||
|
||||
THIS->SetDoorName(name);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
XS(XS_Doors_GetModelName); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_GetModelName)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Doors::GetModelName(THIS)");
|
||||
{
|
||||
Doors * THIS;
|
||||
Const_char * RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetDoorName();
|
||||
sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG;
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Doors_CreateDatabaseEntry); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Doors_CreateDatabaseEntry)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Doors::InsertDoor(THIS)");
|
||||
{
|
||||
Doors * THIS;
|
||||
|
||||
if (sv_derived_from(ST(0), "Doors")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Doors *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Doors");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->CreateDatabaseEntry();
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
XS(boot_Doors); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(boot_Doors)
|
||||
{
|
||||
dXSARGS;
|
||||
char file[256];
|
||||
strncpy(file, __FILE__, 256);
|
||||
file[255] = 0;
|
||||
|
||||
if(items != 1)
|
||||
fprintf(stderr, "boot_quest does not take any arguments.");
|
||||
char buf[128];
|
||||
|
||||
//add the strcpy stuff to get rid of const warnings....
|
||||
|
||||
|
||||
|
||||
XS_VERSION_BOOTCHECK ;
|
||||
newXSproto(strcpy(buf, "GetID"),XS_Doors_GetID, file, "$");
|
||||
newXSproto(strcpy(buf, "SetModelName"),XS_Doors_SetModelName, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetModelName"),XS_Doors_GetModelName, file, "$");
|
||||
newXSproto(strcpy(buf, "GetX"),XS_Doors_GetX, file, "$");
|
||||
newXSproto(strcpy(buf, "GetY"),XS_Doors_GetY, file, "$");
|
||||
newXSproto(strcpy(buf, "GetZ"),XS_Doors_GetZ, file, "$");
|
||||
newXSproto(strcpy(buf, "GetHeading"),XS_Doors_GetHeading, file, "$");
|
||||
newXSproto(strcpy(buf, "SetX"),XS_Doors_SetX, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetY"),XS_Doors_SetY, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetZ"),XS_Doors_SetZ, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetHeading"),XS_Doors_SetHeading, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetLocation"),XS_Doors_SetLocation, file, "$$$$");
|
||||
newXSproto(strcpy(buf, "GetDoorDBID"),XS_Doors_GetDoorDBID, file, "$");
|
||||
newXSproto(strcpy(buf, "GetDoorID"),XS_Doors_GetDoorID, file, "$");
|
||||
newXSproto(strcpy(buf, "SetSize"),XS_Doors_SetSize, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetSize"),XS_Doors_GetSize, file, "$");
|
||||
newXSproto(strcpy(buf, "SetIncline"),XS_Doors_SetIncline, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetIncline"),XS_Doors_GetIncline, file, "$");
|
||||
newXSproto(strcpy(buf, "SetOpenType"),XS_Doors_SetOpenType, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetOpenType"),XS_Doors_GetOpenType, file, "$");
|
||||
newXSproto(strcpy(buf, "SetLockPick"),XS_Doors_SetLockpick, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetLockPick"),XS_Doors_GetLockpick, file, "$");
|
||||
newXSproto(strcpy(buf, "SetKeyItem"),XS_Doors_SetKeyItem, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetKeyItem"),XS_Doors_GetKeyItem, file, "$");
|
||||
newXSproto(strcpy(buf, "SetNoKeyring"),XS_Doors_SetNoKeyring, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetNoKeyring"),XS_Doors_GetNoKeyring, file, "$");
|
||||
newXSproto(strcpy(buf, "CreateDatabaseEntry"),XS_Doors_CreateDatabaseEntry, file, "$");
|
||||
XSRETURN_YES;
|
||||
}
|
||||
#endif //EMBPERL_XS_CLASSES
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,657 @@
|
||||
/*
|
||||
* This file was generated automatically by xsubpp version 1.9508 from the
|
||||
* contents of tmp. Do not edit this file, edit tmp instead.
|
||||
*
|
||||
* ANY CHANGES MADE HERE WILL BE LOST!
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "features.h"
|
||||
#ifdef EMBPERL_XS_CLASSES
|
||||
#include "../common/debug.h"
|
||||
#include "embperl.h"
|
||||
|
||||
#include "groups.h"
|
||||
|
||||
#ifdef THIS /* this macro seems to leak out on some systems */
|
||||
#undef THIS
|
||||
#endif
|
||||
|
||||
|
||||
XS(XS_Group_DisbandGroup); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Group_DisbandGroup)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Group::DisbandGroup(THIS)");
|
||||
{
|
||||
Group * THIS;
|
||||
|
||||
if (sv_derived_from(ST(0), "Group")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Group *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Group");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->DisbandGroup();
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Group_IsGroupMember); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Group_IsGroupMember)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Group::IsGroupMember(THIS, client)");
|
||||
{
|
||||
Group * THIS;
|
||||
bool RETVAL;
|
||||
Mob* client;
|
||||
|
||||
if (sv_derived_from(ST(0), "Group")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Group *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Group");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
if (sv_derived_from(ST(1), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(1)));
|
||||
client = INT2PTR(Mob *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "client is not of type Mob");
|
||||
if(client == NULL)
|
||||
Perl_croak(aTHX_ "client is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->IsGroupMember(client);
|
||||
ST(0) = boolSV(RETVAL);
|
||||
sv_2mortal(ST(0));
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Group_CastGroupSpell); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Group_CastGroupSpell)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 3)
|
||||
Perl_croak(aTHX_ "Usage: Group::CastGroupSpell(THIS, caster, spellid)");
|
||||
{
|
||||
Group * THIS;
|
||||
Mob* caster;
|
||||
uint16 spellid = (uint16)SvUV(ST(2));
|
||||
|
||||
if (sv_derived_from(ST(0), "Group")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Group *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Group");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
if (sv_derived_from(ST(1), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(1)));
|
||||
caster = INT2PTR(Mob *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "caster is not of type Mob");
|
||||
if(caster == NULL)
|
||||
Perl_croak(aTHX_ "caster is NULL, avoiding crash.");
|
||||
|
||||
THIS->CastGroupSpell(caster, spellid);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Group_SplitExp); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Group_SplitExp)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 3)
|
||||
Perl_croak(aTHX_ "Usage: Group::SplitExp(THIS, exp, other)");
|
||||
{
|
||||
Group * THIS;
|
||||
uint32 exp = (uint32)SvUV(ST(1));
|
||||
Mob* other;
|
||||
|
||||
if (sv_derived_from(ST(0), "Group")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Group *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Group");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
if (sv_derived_from(ST(2), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(2)));
|
||||
other = INT2PTR(Mob *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "other is not of type Mob");
|
||||
if(other == NULL)
|
||||
Perl_croak(aTHX_ "other is NULL, avoiding crash.");
|
||||
|
||||
THIS->SplitExp(exp, other);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Group_GroupMessage); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Group_GroupMessage)
|
||||
{
|
||||
dXSARGS;
|
||||
if ((items != 3) && (items != 4)) // the 3 item version is kept for backwards compatability
|
||||
Perl_croak(aTHX_ "Usage: Group::GroupMessage(THIS, sender, language, message)");
|
||||
{
|
||||
Group * THIS;
|
||||
Mob* sender;
|
||||
uint8 language;
|
||||
char* message;
|
||||
|
||||
if (sv_derived_from(ST(0), "Group")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Group *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Group");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
if (sv_derived_from(ST(1), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(1)));
|
||||
sender = INT2PTR(Mob *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "sender is not of type Mob");
|
||||
if(sender == NULL)
|
||||
Perl_croak(aTHX_ "sender is NULL, avoiding crash.");
|
||||
|
||||
if (items == 4) {
|
||||
language = (uint8)SvUV(ST(2));
|
||||
if ((language >= MAX_PP_LANGUAGE) || (language < 0))
|
||||
language = 0;
|
||||
message = (char *)SvPV_nolen(ST(3));
|
||||
THIS->GroupMessage(sender, language, 100, message);
|
||||
}
|
||||
else { // if no language is specificed, send it in common
|
||||
message = (char *)SvPV_nolen(ST(2));
|
||||
THIS->GroupMessage(sender,0, 100, message);
|
||||
}
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Group_GetTotalGroupDamage); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Group_GetTotalGroupDamage)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Group::GetTotalGroupDamage(THIS, other)");
|
||||
{
|
||||
Group * THIS;
|
||||
uint32 RETVAL;
|
||||
dXSTARG;
|
||||
Mob* other;
|
||||
|
||||
if (sv_derived_from(ST(0), "Group")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Group *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Group");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
if (sv_derived_from(ST(1), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(1)));
|
||||
other = INT2PTR(Mob *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "other is not of type Mob");
|
||||
if(other == NULL)
|
||||
Perl_croak(aTHX_ "other is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetTotalGroupDamage(other);
|
||||
XSprePUSH; PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Group_SplitMoney); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Group_SplitMoney)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 5)
|
||||
Perl_croak(aTHX_ "Usage: Group::SplitMoney(THIS, copper, silver, gold, platinum)");
|
||||
{
|
||||
Group * THIS;
|
||||
uint32 copper = (uint32)SvUV(ST(1));
|
||||
uint32 silver = (uint32)SvUV(ST(2));
|
||||
uint32 gold = (uint32)SvUV(ST(3));
|
||||
uint32 platinum = (uint32)SvUV(ST(4));
|
||||
|
||||
if (sv_derived_from(ST(0), "Group")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Group *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Group");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->SplitMoney(copper, silver, gold, platinum);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Group_SetLeader); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Group_SetLeader)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Group::SetLeader(THIS, newleader)");
|
||||
{
|
||||
Group * THIS;
|
||||
Mob* newleader;
|
||||
|
||||
if (sv_derived_from(ST(0), "Group")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Group *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Group");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
if (sv_derived_from(ST(1), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(1)));
|
||||
newleader = INT2PTR(Mob *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "newleader is not of type Mob");
|
||||
if(newleader == NULL)
|
||||
Perl_croak(aTHX_ "newleader is NULL, avoiding crash.");
|
||||
|
||||
THIS->SetLeader(newleader);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Group_GetLeader); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Group_GetLeader)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Group::GetLeader(THIS)");
|
||||
{
|
||||
Group * THIS;
|
||||
Mob * RETVAL;
|
||||
|
||||
if (sv_derived_from(ST(0), "Group")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Group *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Group");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetLeader();
|
||||
ST(0) = sv_newmortal();
|
||||
sv_setref_pv(ST(0), "Mob", (void*)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Group_GetLeaderName); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Group_GetLeaderName)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Group::GetLeaderName(THIS)");
|
||||
{
|
||||
Group * THIS;
|
||||
char * RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Group")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Group *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Group");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetLeaderName();
|
||||
sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG;
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Group_SendHPPacketsTo); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Group_SendHPPacketsTo)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Group::SendHPPacketsTo(THIS, newmember)");
|
||||
{
|
||||
Group * THIS;
|
||||
Mob* newmember;
|
||||
|
||||
if (sv_derived_from(ST(0), "Group")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Group *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Group");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
if (sv_derived_from(ST(1), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(1)));
|
||||
newmember = INT2PTR(Mob *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "newmember is not of type Mob");
|
||||
if(newmember == NULL)
|
||||
Perl_croak(aTHX_ "newmember is NULL, avoiding crash.");
|
||||
|
||||
THIS->SendHPPacketsTo(newmember);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Group_SendHPPacketsFrom); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Group_SendHPPacketsFrom)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Group::SendHPPacketsFrom(THIS, newmember)");
|
||||
{
|
||||
Group * THIS;
|
||||
Mob* newmember;
|
||||
|
||||
if (sv_derived_from(ST(0), "Group")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Group *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Group");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
if (sv_derived_from(ST(1), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(1)));
|
||||
newmember = INT2PTR(Mob *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "newmember is not of type Mob");
|
||||
if(newmember == NULL)
|
||||
Perl_croak(aTHX_ "newmember is NULL, avoiding crash.");
|
||||
|
||||
THIS->SendHPPacketsFrom(newmember);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Group_IsLeader); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Group_IsLeader)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Group::IsLeader(THIS, leadertest)");
|
||||
{
|
||||
Group * THIS;
|
||||
bool RETVAL;
|
||||
Mob* leadertest;
|
||||
|
||||
if (sv_derived_from(ST(0), "Group")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Group *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Group");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
if (sv_derived_from(ST(1), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(1)));
|
||||
leadertest = INT2PTR(Mob *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "leadertest is not of type Mob");
|
||||
if(leadertest == NULL)
|
||||
Perl_croak(aTHX_ "leadertest is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->IsLeader(leadertest);
|
||||
ST(0) = boolSV(RETVAL);
|
||||
sv_2mortal(ST(0));
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Group_GroupCount); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Group_GroupCount)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Group::GroupCount(THIS)");
|
||||
{
|
||||
Group * THIS;
|
||||
uint8 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Group")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Group *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Group");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GroupCount();
|
||||
XSprePUSH; PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Group_GetHighestLevel); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Group_GetHighestLevel)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Group::GetHighestLevel(THIS)");
|
||||
{
|
||||
Group * THIS;
|
||||
uint32 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Group")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Group *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Group");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetHighestLevel();
|
||||
XSprePUSH; PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Group_TeleportGroup); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Group_TeleportGroup)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 7)
|
||||
Perl_croak(aTHX_ "Usage: Group::TeleportGroup(THIS, sender, zoneID, x, y, z, heading)");
|
||||
{
|
||||
Group * THIS;
|
||||
Mob* sender;
|
||||
uint32 zoneID = (uint32)SvUV(ST(2));
|
||||
float x = (float)SvNV(ST(3));
|
||||
float y = (float)SvNV(ST(4));
|
||||
float z = (float)SvNV(ST(5));
|
||||
float heading = (float)SvNV(ST(6));
|
||||
|
||||
if (sv_derived_from(ST(0), "Group")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Group *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Group");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
if (sv_derived_from(ST(1), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(1)));
|
||||
sender = INT2PTR(Mob *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "sender is not of type Mob");
|
||||
if(sender == NULL)
|
||||
Perl_croak(aTHX_ "sender is NULL, avoiding crash.");
|
||||
|
||||
THIS->TeleportGroup(sender, zoneID, 0, x, y, z, heading);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Group_GetID); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Group_GetID)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Group::GetID(THIS)");
|
||||
{
|
||||
Group * THIS;
|
||||
uint32 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Group")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Group *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Group");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetID();
|
||||
XSprePUSH; PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Group_GetMember);
|
||||
XS(XS_Group_GetMember)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Group::GetMember(THIS, index)");
|
||||
{
|
||||
Group * THIS;
|
||||
Mob* member;
|
||||
Client* RETVAL = NULL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Group")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Group *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Group");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
int index = (int)SvUV(ST(1));
|
||||
if (index < 0 || index > 5)
|
||||
RETVAL = NULL;
|
||||
else {
|
||||
member = THIS->members[index];
|
||||
if (member != NULL)
|
||||
RETVAL = member->CastToClient();
|
||||
}
|
||||
|
||||
ST(0) = sv_newmortal();
|
||||
sv_setref_pv(ST(0), "Client", (void*)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
XS(boot_Group); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(boot_Group)
|
||||
{
|
||||
dXSARGS;
|
||||
char file[256];
|
||||
strncpy(file, __FILE__, 256);
|
||||
file[255] = 0;
|
||||
|
||||
if(items != 1)
|
||||
fprintf(stderr, "boot_quest does not take any arguments.");
|
||||
char buf[128];
|
||||
|
||||
//add the strcpy stuff to get rid of const warnings....
|
||||
|
||||
|
||||
|
||||
XS_VERSION_BOOTCHECK ;
|
||||
|
||||
newXSproto(strcpy(buf, "DisbandGroup"), XS_Group_DisbandGroup, file, "$");
|
||||
newXSproto(strcpy(buf, "IsGroupMember"), XS_Group_IsGroupMember, file, "$$");
|
||||
newXSproto(strcpy(buf, "CastGroupSpell"), XS_Group_CastGroupSpell, file, "$$$");
|
||||
newXSproto(strcpy(buf, "SplitExp"), XS_Group_SplitExp, file, "$$$");
|
||||
newXSproto(strcpy(buf, "GroupMessage"), XS_Group_GroupMessage, file, "$$$");
|
||||
newXSproto(strcpy(buf, "GetTotalGroupDamage"), XS_Group_GetTotalGroupDamage, file, "$$");
|
||||
newXSproto(strcpy(buf, "SplitMoney"), XS_Group_SplitMoney, file, "$$$$$");
|
||||
newXSproto(strcpy(buf, "SetLeader"), XS_Group_SetLeader, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetLeader"), XS_Group_GetLeader, file, "$");
|
||||
newXSproto(strcpy(buf, "GetLeaderName"), XS_Group_GetLeaderName, file, "$");
|
||||
newXSproto(strcpy(buf, "SendHPPacketsTo"), XS_Group_SendHPPacketsTo, file, "$$");
|
||||
newXSproto(strcpy(buf, "SendHPPacketsFrom"), XS_Group_SendHPPacketsFrom, file, "$$");
|
||||
newXSproto(strcpy(buf, "IsLeader"), XS_Group_IsLeader, file, "$$");
|
||||
newXSproto(strcpy(buf, "GroupCount"), XS_Group_GroupCount, file, "$");
|
||||
newXSproto(strcpy(buf, "GetHighestLevel"), XS_Group_GetHighestLevel, file, "$");
|
||||
newXSproto(strcpy(buf, "TeleportGroup"), XS_Group_TeleportGroup, file, "$$$$$$$");
|
||||
newXSproto(strcpy(buf, "GetID"), XS_Group_GetID, file, "$");
|
||||
newXSproto(strcpy(buf, "GetMember"), XS_Group_GetMember, file, "$$");
|
||||
XSRETURN_YES;
|
||||
}
|
||||
|
||||
#endif //EMBPERL_XS_CLASSES
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2009 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "features.h"
|
||||
#include "client.h"
|
||||
#ifdef EMBPERL_XS_CLASSES
|
||||
#include "../common/debug.h"
|
||||
#include "embperl.h"
|
||||
|
||||
#include "../common/linked_list.h"
|
||||
#include "hate_list.h"
|
||||
|
||||
#ifdef THIS /* this macro seems to leak out on some systems */
|
||||
#undef THIS
|
||||
#endif
|
||||
|
||||
XS(XS_HateEntry_GetEnt); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_HateEntry_GetEnt)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: HateEntry::GetData(THIS)");
|
||||
{
|
||||
tHateEntry * THIS;
|
||||
Mob * RETVAL;
|
||||
|
||||
if (sv_derived_from(ST(0), "HateEntry")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(tHateEntry *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type tHateEntry");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->ent;
|
||||
ST(0) = sv_newmortal();
|
||||
sv_setref_pv(ST(0), "Mob", (void*)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_HateEntry_GetHate); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_HateEntry_GetHate)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: HateEntry::GetHate(THIS)");
|
||||
{
|
||||
tHateEntry * THIS;
|
||||
int32 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "HateEntry")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(tHateEntry *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type tHateEntry");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->hate;
|
||||
XSprePUSH; PUSHi((IV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_HateEntry_GetDamage); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_HateEntry_GetDamage)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: HateEntry::GetDamage(THIS)");
|
||||
{
|
||||
tHateEntry * THIS;
|
||||
int32 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "HateEntry")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(tHateEntry *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type tHateEntry");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->damage;
|
||||
XSprePUSH; PUSHi((IV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
|
||||
XS(boot_HateEntry);
|
||||
XS(boot_HateEntry)
|
||||
{
|
||||
dXSARGS;
|
||||
char file[256];
|
||||
strncpy(file, __FILE__, 256);
|
||||
file[255] = 0;
|
||||
|
||||
if(items != 1)
|
||||
fprintf(stderr, "boot_quest does not take any arguments.");
|
||||
char buf[128];
|
||||
|
||||
//add the strcpy stuff to get rid of const warnings....
|
||||
|
||||
XS_VERSION_BOOTCHECK ;
|
||||
|
||||
newXSproto(strcpy(buf, "GetEnt"), XS_HateEntry_GetEnt, file, "$");
|
||||
newXSproto(strcpy(buf, "GetDamage"), XS_HateEntry_GetDamage, file, "$");
|
||||
newXSproto(strcpy(buf, "GetHate"), XS_HateEntry_GetHate, file, "$");
|
||||
|
||||
XSRETURN_YES;
|
||||
}
|
||||
|
||||
#endif //EMBPERL_XS_CLASSES
|
||||
+8351
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user