mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-20 05:01:29 +00:00
Merge branch 'master' of https://github.com/EQEmu/Server
This commit is contained in:
commit
5881eabce9
@ -1,5 +1,19 @@
|
|||||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
|
== 03/05/2016 ==
|
||||||
|
mackal: Implement extra bind points (secondary recall)
|
||||||
|
For SE_Gate, base2 is which bind to use (starting at 1)
|
||||||
|
For SE_BindAffinity, base1 is which bind to set (starting at 1)
|
||||||
|
For SE_GateCastersBindpoint, base1 is which bind to use (starting at 1)
|
||||||
|
There was actually no spells that don't send to the main bind, but it uses a base1 of 1 which matches with SE_Gate
|
||||||
|
This also doesn't break anything
|
||||||
|
|
||||||
|
== 03/01/2016 ==
|
||||||
|
Uleat: Fix for LDoN treasure 'npcs' not leaving a corpse (please report any issues..)
|
||||||
|
|
||||||
|
== 02/29/2016 ==
|
||||||
|
Uleat: Change in AddItemBonuses - now includes ammo slot for skill mods only. Defined SoD- client SkillModMax packet property (client does not show..but, does enforce.)
|
||||||
|
|
||||||
== 02/11/2016 ==
|
== 02/11/2016 ==
|
||||||
Hateborne: Added IgnoreSpellDmgLvlRestriction rule (boolean) to ignore the 5 level spread when checking to add SpellDmg
|
Hateborne: Added IgnoreSpellDmgLvlRestriction rule (boolean) to ignore the 5 level spread when checking to add SpellDmg
|
||||||
|
|
||||||
|
|||||||
@ -636,11 +636,11 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe
|
|||||||
);
|
);
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
/* Save Bind Points */
|
/* Save Bind Points */
|
||||||
query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)"
|
query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)"
|
||||||
" VALUES (%u, %u, %u, %f, %f, %f, %f, %i), "
|
" VALUES (%u, %u, %u, %f, %f, %f, %f, %i), "
|
||||||
"(%u, %u, %u, %f, %f, %f, %f, %i)",
|
"(%u, %u, %u, %f, %f, %f, %f, %i)",
|
||||||
character_id, pp->binds[0].zoneId, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading, 0,
|
character_id, pp->binds[0].zoneId, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading, 0,
|
||||||
character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading, 1
|
character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading, 4
|
||||||
); results = QueryDatabase(query);
|
); results = QueryDatabase(query);
|
||||||
|
|
||||||
/* Save Skills */
|
/* Save Skills */
|
||||||
|
|||||||
@ -2230,11 +2230,12 @@ void ItemInst::ScaleItem() {
|
|||||||
m_scaledItem->Mana = (int32)((float)m_item->Mana*Mult);
|
m_scaledItem->Mana = (int32)((float)m_item->Mana*Mult);
|
||||||
m_scaledItem->AC = (int32)((float)m_item->AC*Mult);
|
m_scaledItem->AC = (int32)((float)m_item->AC*Mult);
|
||||||
|
|
||||||
m_scaledItem->SkillModValue = (int32)((float)m_item->SkillModValue*Mult);
|
// check these..some may not need to be modified (really need to check all stats/bonuses)
|
||||||
m_scaledItem->BaneDmgAmt = (int8)((float)m_item->BaneDmgAmt*Mult);
|
//m_scaledItem->SkillModValue = (int32)((float)m_item->SkillModValue*Mult);
|
||||||
m_scaledItem->BardValue = (int32)((float)m_item->BardValue*Mult);
|
//m_scaledItem->BaneDmgAmt = (int8)((float)m_item->BaneDmgAmt*Mult); // watch (10 entries with charmfileid)
|
||||||
m_scaledItem->ElemDmgAmt = (uint8)((float)m_item->ElemDmgAmt*Mult);
|
m_scaledItem->BardValue = (int32)((float)m_item->BardValue*Mult); // watch (no entries with charmfileid)
|
||||||
m_scaledItem->Damage = (uint32)((float)m_item->Damage*Mult);
|
m_scaledItem->ElemDmgAmt = (uint8)((float)m_item->ElemDmgAmt*Mult); // watch (no entries with charmfileid)
|
||||||
|
m_scaledItem->Damage = (uint32)((float)m_item->Damage*Mult); // watch
|
||||||
|
|
||||||
m_scaledItem->CombatEffects = (int8)((float)m_item->CombatEffects*Mult);
|
m_scaledItem->CombatEffects = (int8)((float)m_item->CombatEffects*Mult);
|
||||||
m_scaledItem->Shielding = (int8)((float)m_item->Shielding*Mult);
|
m_scaledItem->Shielding = (int8)((float)m_item->Shielding*Mult);
|
||||||
|
|||||||
@ -975,8 +975,8 @@ namespace RoF
|
|||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->drop_id); // Some unique id
|
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->drop_id); // Some unique id
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Same for all objects in the zone
|
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Same for all objects in the zone
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->heading);
|
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->heading);
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // Normally 0, but seen (float)255.0 as well
|
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // X tilt
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->solidtype); // Unknown
|
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // Y tilt
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->size != 0 && (float)emu->size < 5000.f ? (float)((float)emu->size / 100.0f) : 1.f ); // This appears to be the size field. Hackish logic because some PEQ DB items were corrupt.
|
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->size != 0 && (float)emu->size < 5000.f ? (float)((float)emu->size / 100.0f) : 1.f ); // This appears to be the size field. Hackish logic because some PEQ DB items were corrupt.
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y);
|
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y);
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x);
|
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x);
|
||||||
|
|||||||
@ -1046,8 +1046,8 @@ namespace RoF2
|
|||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->drop_id); // Some unique id
|
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->drop_id); // Some unique id
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Same for all objects in the zone
|
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Same for all objects in the zone
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->heading);
|
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->heading);
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // Normally 0, but seen (float)255.0 as well
|
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // X tilt
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->solidtype); // Unknown
|
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // Y tilt
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->size != 0 && (float)emu->size < 5000.f ? (float)((float)emu->size / 100.0f) : 1.f ); // This appears to be the size field. Hackish logic because some PEQ DB items were corrupt.
|
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->size != 0 && (float)emu->size < 5000.f ? (float)((float)emu->size / 100.0f) : 1.f ); // This appears to be the size field. Hackish logic because some PEQ DB items were corrupt.
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y);
|
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y);
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x);
|
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x);
|
||||||
|
|||||||
@ -2845,7 +2845,8 @@ struct Object_Struct {
|
|||||||
/*00*/ uint32 drop_id; // Unique object id for zone
|
/*00*/ uint32 drop_id; // Unique object id for zone
|
||||||
/*00*/ uint32 unknown024; // 53 9e f9 7e - same for all objects in the zone?
|
/*00*/ uint32 unknown024; // 53 9e f9 7e - same for all objects in the zone?
|
||||||
/*00*/ float heading; // heading
|
/*00*/ float heading; // heading
|
||||||
/*00*/ float unknown032[2]; // 00 00 00 00 00 00 00 00
|
/*00*/ float x_tilt; //Tilt entire object on X axis
|
||||||
|
/*00*/ float y_tilt; //Tilt entire object on Y axis
|
||||||
/*00*/ float size; // Size - default 1
|
/*00*/ float size; // Size - default 1
|
||||||
/*00*/ float z; // z coord
|
/*00*/ float z; // z coord
|
||||||
/*00*/ float x; // x coord
|
/*00*/ float x; // x coord
|
||||||
|
|||||||
@ -2873,7 +2873,8 @@ struct Object_Struct {
|
|||||||
/*00*/ uint32 drop_id; // Unique object id for zone
|
/*00*/ uint32 drop_id; // Unique object id for zone
|
||||||
/*00*/ uint32 unknown024; // 53 9e f9 7e - same for all objects in the zone?
|
/*00*/ uint32 unknown024; // 53 9e f9 7e - same for all objects in the zone?
|
||||||
/*00*/ float heading; // heading
|
/*00*/ float heading; // heading
|
||||||
/*00*/ float unknown032[2]; // 00 00 00 00 00 00 00 00
|
/*00*/ float x_tilt; //Tilt entire object on X axis
|
||||||
|
/*00*/ float y_tilt; //Tilt entire object on Y axis
|
||||||
/*00*/ float size; // Size - default 1
|
/*00*/ float size; // Size - default 1
|
||||||
/*00*/ float z; // z coord
|
/*00*/ float z; // z coord
|
||||||
/*00*/ float x; // x coord
|
/*00*/ float x; // x coord
|
||||||
|
|||||||
@ -3661,7 +3661,7 @@ namespace SoD
|
|||||||
ibs.Races = item->Races;
|
ibs.Races = item->Races;
|
||||||
ibs.Deity = item->Deity;
|
ibs.Deity = item->Deity;
|
||||||
ibs.SkillModValue = item->SkillModValue;
|
ibs.SkillModValue = item->SkillModValue;
|
||||||
ibs.unknown6 = 0;
|
ibs.SkillModMax = item->SkillModMax;
|
||||||
ibs.SkillModType = item->SkillModType;
|
ibs.SkillModType = item->SkillModType;
|
||||||
ibs.BaneDmgRace = item->BaneDmgRace;
|
ibs.BaneDmgRace = item->BaneDmgRace;
|
||||||
ibs.BaneDmgBody = item->BaneDmgBody;
|
ibs.BaneDmgBody = item->BaneDmgBody;
|
||||||
|
|||||||
@ -4006,7 +4006,7 @@ struct ItemBodyStruct
|
|||||||
uint32 Races;
|
uint32 Races;
|
||||||
uint32 Deity;
|
uint32 Deity;
|
||||||
int32 SkillModValue;
|
int32 SkillModValue;
|
||||||
uint32 unknown6;
|
uint32 SkillModMax;
|
||||||
uint32 SkillModType;
|
uint32 SkillModType;
|
||||||
uint32 BaneDmgRace;
|
uint32 BaneDmgRace;
|
||||||
uint32 BaneDmgBody;
|
uint32 BaneDmgBody;
|
||||||
|
|||||||
@ -2983,7 +2983,7 @@ namespace SoF
|
|||||||
ibs.Races = item->Races;
|
ibs.Races = item->Races;
|
||||||
ibs.Deity = item->Deity;
|
ibs.Deity = item->Deity;
|
||||||
ibs.SkillModValue = item->SkillModValue;
|
ibs.SkillModValue = item->SkillModValue;
|
||||||
ibs.unknown6 = 0;
|
ibs.SkillModMax = item->SkillModMax;
|
||||||
ibs.SkillModType = item->SkillModType;
|
ibs.SkillModType = item->SkillModType;
|
||||||
ibs.BaneDmgRace = item->BaneDmgRace;
|
ibs.BaneDmgRace = item->BaneDmgRace;
|
||||||
ibs.BaneDmgBody = item->BaneDmgBody;
|
ibs.BaneDmgBody = item->BaneDmgBody;
|
||||||
|
|||||||
@ -3861,7 +3861,7 @@ struct ItemBodyStruct
|
|||||||
uint32 Races;
|
uint32 Races;
|
||||||
uint32 Deity;
|
uint32 Deity;
|
||||||
int32 SkillModValue;
|
int32 SkillModValue;
|
||||||
uint32 unknown6;
|
uint32 SkillModMax;
|
||||||
uint32 SkillModType;
|
uint32 SkillModType;
|
||||||
uint32 BaneDmgRace;
|
uint32 BaneDmgRace;
|
||||||
uint32 BaneDmgBody;
|
uint32 BaneDmgBody;
|
||||||
|
|||||||
@ -39,7 +39,7 @@ These fields must be in the order of how they are serialized!
|
|||||||
/* 030 */ I(AC)
|
/* 030 */ I(AC)
|
||||||
/* 031 */ I(Deity)
|
/* 031 */ I(Deity)
|
||||||
/* 032 */ I(SkillModValue)
|
/* 032 */ I(SkillModValue)
|
||||||
/* 033 */ C("0")
|
/* 033 */ I(SkillModMax)
|
||||||
/* 034 */ I(SkillModType)
|
/* 034 */ I(SkillModType)
|
||||||
/* 035 */ I(BaneDmgRace)
|
/* 035 */ I(BaneDmgRace)
|
||||||
/* 036 */ I(BaneDmgAmt)
|
/* 036 */ I(BaneDmgAmt)
|
||||||
|
|||||||
@ -857,8 +857,8 @@ namespace UF
|
|||||||
// This next field is actually a float. There is a groundspawn in freeportwest (sack of money sitting on some barrels) which requires this
|
// This next field is actually a float. There is a groundspawn in freeportwest (sack of money sitting on some barrels) which requires this
|
||||||
// field to be set to (float)255.0 to appear at all, and also the size field below to be 5, to be the correct size. I think SoD has the same
|
// field to be set to (float)255.0 to appear at all, and also the size field below to be 5, to be the correct size. I think SoD has the same
|
||||||
// issue.
|
// issue.
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); //X tilt
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->solidtype); // Unknown, observed 0
|
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); //Y tilt
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->size != 0 && (float)emu->size < 5000.f ? (float)((float)emu->size / 100.0f) : 1.f ); // This appears to be the size field. Hackish logic because some PEQ DB items were corrupt.
|
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->size != 0 && (float)emu->size < 5000.f ? (float)((float)emu->size / 100.0f) : 1.f ); // This appears to be the size field. Hackish logic because some PEQ DB items were corrupt.
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y);
|
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y);
|
||||||
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x);
|
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x);
|
||||||
|
|||||||
@ -2450,7 +2450,8 @@ struct Object_Struct {
|
|||||||
/*20*/ uint32 unknown020; // 00 00 00 00
|
/*20*/ uint32 unknown020; // 00 00 00 00
|
||||||
/*24*/ uint32 unknown024; // 53 9e f9 7e - same for all objects in the zone?
|
/*24*/ uint32 unknown024; // 53 9e f9 7e - same for all objects in the zone?
|
||||||
/*40*/ float heading; // heading
|
/*40*/ float heading; // heading
|
||||||
/*32*/ uint8 unknown032[8]; // 00 00 00 00 00 00 00 00
|
/*00*/ float x_tilt; //Tilt entire object on X axis
|
||||||
|
/*00*/ float y_tilt; //Tilt entire object on Y axis
|
||||||
/*28*/ float size; // Size - default 1
|
/*28*/ float size; // Size - default 1
|
||||||
/*44*/ float z; // z coord
|
/*44*/ float z; // z coord
|
||||||
/*48*/ float x; // x coord
|
/*48*/ float x; // x coord
|
||||||
|
|||||||
@ -126,6 +126,7 @@ RULE_INT(Character, InvSnapshotMinIntervalM, 180) // Minimum time (in minutes) b
|
|||||||
RULE_INT(Character, InvSnapshotMinRetryM, 30) // Time (in minutes) to re-attempt an inventory snapshot after a failure
|
RULE_INT(Character, InvSnapshotMinRetryM, 30) // Time (in minutes) to re-attempt an inventory snapshot after a failure
|
||||||
RULE_INT(Character, InvSnapshotHistoryD, 30) // Time (in days) to keep snapshot entries
|
RULE_INT(Character, InvSnapshotHistoryD, 30) // Time (in days) to keep snapshot entries
|
||||||
RULE_BOOL(Character, RestrictSpellScribing, false) // Restricts spell scribing to allowable races/classes of spell scroll, if true
|
RULE_BOOL(Character, RestrictSpellScribing, false) // Restricts spell scribing to allowable races/classes of spell scroll, if true
|
||||||
|
RULE_BOOL(Character, UseStackablePickPocketing, true) // Allows stackable pickpocketed items to stack instead of only being allowed in empty inventory slots
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Mercs)
|
RULE_CATEGORY(Mercs)
|
||||||
|
|||||||
@ -30,7 +30,7 @@
|
|||||||
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define CURRENT_BINARY_DATABASE_VERSION 9095
|
#define CURRENT_BINARY_DATABASE_VERSION 9096
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9000
|
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9000
|
||||||
#else
|
#else
|
||||||
|
|||||||
@ -62,6 +62,18 @@ int main(int argc, char **argv) {
|
|||||||
database.LoadLogSettings(Log.log_settings);
|
database.LoadLogSettings(Log.log_settings);
|
||||||
Log.StartFileLogs();
|
Log.StartFileLogs();
|
||||||
|
|
||||||
|
database.LoadVariables();
|
||||||
|
|
||||||
|
/* If we're running shared memory and hotfix has no custom name, we probably want to start from scratch... */
|
||||||
|
char db_hotfix_name[256] = { 0 };
|
||||||
|
if (database.GetVariable("hotfix_name", db_hotfix_name, 256)) {
|
||||||
|
if (strlen(db_hotfix_name) > 0 && strcasecmp("hotfix_", db_hotfix_name) == 0) {
|
||||||
|
Log.Out(Logs::General, Logs::Status, "Current hotfix in variables is the default %s, clearing out variable", db_hotfix_name);
|
||||||
|
std::string query = StringFormat("UPDATE `variables` SET `value`='' WHERE (`varname`='hotfix_name')");
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string hotfix_name = "";
|
std::string hotfix_name = "";
|
||||||
bool load_all = true;
|
bool load_all = true;
|
||||||
bool load_items = false;
|
bool load_items = false;
|
||||||
|
|||||||
@ -349,6 +349,7 @@
|
|||||||
9093|2015_12_21_items_updates_evoitem.sql|SHOW COLUMNS FROM `items` LIKE 'evoitem'|empty|
|
9093|2015_12_21_items_updates_evoitem.sql|SHOW COLUMNS FROM `items` LIKE 'evoitem'|empty|
|
||||||
9094|2015_12_29_quest_zone_events.sql|SELECT * FROM perl_event_export_settings WHERE event_description = 'EVENT_SPAWN_ZONE'|empty|
|
9094|2015_12_29_quest_zone_events.sql|SELECT * FROM perl_event_export_settings WHERE event_description = 'EVENT_SPAWN_ZONE'|empty|
|
||||||
9095|2016_01_08_command_find_aliases.sql|SELECT * FROM `command_settings` WHERE `command` LIKE 'findaliases'|empty|
|
9095|2016_01_08_command_find_aliases.sql|SELECT * FROM `command_settings` WHERE `command` LIKE 'findaliases'|empty|
|
||||||
|
9096|2016_03_05_secondary_recall.sql|SHOW COLUMNS FROM `character_bind` LIKE 'slot'|empty|
|
||||||
|
|
||||||
# Upgrade conditions:
|
# Upgrade conditions:
|
||||||
# This won't be needed after this system is implemented, but it is used database that are not
|
# This won't be needed after this system is implemented, but it is used database that are not
|
||||||
|
|||||||
6
utils/sql/git/required/2016_03_05_secondary_recall.sql
Normal file
6
utils/sql/git/required/2016_03_05_secondary_recall.sql
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
ALTER TABLE `character_bind` ADD `slot` int(4) AFTER `id`;
|
||||||
|
UPDATE `character_bind` SET `slot`='0' WHERE `is_home`=0;
|
||||||
|
UPDATE `character_bind` SET `slot`='4' WHERE `is_home`=1;
|
||||||
|
ALTER TABLE `character_bind` DROP PRIMARY KEY, ADD PRIMARY KEY(`id`, `slot`);
|
||||||
|
ALTER TABLE `character_bind` DROP COLUMN `is_home`;
|
||||||
|
|
||||||
@ -159,10 +159,10 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Set Bind Point Data for any character that may possibly be missing it for any reason */
|
/* Set Bind Point Data for any character that may possibly be missing it for any reason */
|
||||||
cquery = StringFormat("SELECT `zone_id`, `instance_id`, `x`, `y`, `z`, `heading`, `is_home` FROM `character_bind` WHERE `id` = %i LIMIT 2", character_id);
|
cquery = StringFormat("SELECT `zone_id`, `instance_id`, `x`, `y`, `z`, `heading`, `slot` FROM `character_bind` WHERE `id` = %i LIMIT 5", character_id);
|
||||||
auto results_bind = database.QueryDatabase(cquery);
|
auto results_bind = database.QueryDatabase(cquery);
|
||||||
for (auto row_b = results_bind.begin(); row_b != results_bind.end(); ++row_b) {
|
for (auto row_b = results_bind.begin(); row_b != results_bind.end(); ++row_b) {
|
||||||
if (row_b[6] && atoi(row_b[6]) == 1){ has_home = 1; }
|
if (row_b[6] && atoi(row_b[6]) == 4){ has_home = 1; }
|
||||||
if (row_b[6] && atoi(row_b[6]) == 0){ has_bind = 1; }
|
if (row_b[6] && atoi(row_b[6]) == 0){ has_bind = 1; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,14 +189,14 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou
|
|||||||
pp.binds[0] = pp.binds[4];
|
pp.binds[0] = pp.binds[4];
|
||||||
/* If no home bind set, set it */
|
/* If no home bind set, set it */
|
||||||
if (has_home == 0) {
|
if (has_home == 0) {
|
||||||
std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)"
|
std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)"
|
||||||
" VALUES (%u, %u, %u, %f, %f, %f, %f, %i)",
|
" VALUES (%u, %u, %u, %f, %f, %f, %f, %i)",
|
||||||
character_id, pp.binds[4].zoneId, 0, pp.binds[4].x, pp.binds[4].y, pp.binds[4].z, pp.binds[4].heading, 1);
|
character_id, pp.binds[4].zoneId, 0, pp.binds[4].x, pp.binds[4].y, pp.binds[4].z, pp.binds[4].heading, 4);
|
||||||
auto results_bset = QueryDatabase(query);
|
auto results_bset = QueryDatabase(query);
|
||||||
}
|
}
|
||||||
/* If no regular bind set, set it */
|
/* If no regular bind set, set it */
|
||||||
if (has_bind == 0) {
|
if (has_bind == 0) {
|
||||||
std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)"
|
std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)"
|
||||||
" VALUES (%u, %u, %u, %f, %f, %f, %f, %i)",
|
" VALUES (%u, %u, %u, %f, %f, %f, %f, %i)",
|
||||||
character_id, pp.binds[0].zoneId, 0, pp.binds[0].x, pp.binds[0].y, pp.binds[0].z, pp.binds[0].heading, 0);
|
character_id, pp.binds[0].zoneId, 0, pp.binds[0].x, pp.binds[0].y, pp.binds[0].z, pp.binds[0].heading, 0);
|
||||||
auto results_bset = QueryDatabase(query);
|
auto results_bset = QueryDatabase(query);
|
||||||
@ -285,7 +285,7 @@ int WorldDatabase::MoveCharacterToBind(int CharID, uint8 bindnum)
|
|||||||
bindnum = 0;
|
bindnum = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string query = StringFormat("SELECT zone_id, instance_id, x, y, z FROM character_bind WHERE id = %u AND is_home = %u LIMIT 1", CharID, bindnum == 4 ? 1 : 0);
|
std::string query = StringFormat("SELECT zone_id, instance_id, x, y, z FROM character_bind WHERE id = %u AND slot = %u LIMIT 1", CharID, bindnum);
|
||||||
auto results = database.QueryDatabase(query);
|
auto results = database.QueryDatabase(query);
|
||||||
if(!results.Success() || results.RowCount() == 0) {
|
if(!results.Success() || results.RowCount() == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
224
zone/attack.cpp
224
zone/attack.cpp
@ -1874,50 +1874,52 @@ void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attack_skill) {
|
bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attack_skill)
|
||||||
Log.Out(Logs::Detail, Logs::Combat, "Fatal blow dealt by %s with %d damage, spell %d, skill %d", killer_mob->GetName(), damage, spell, attack_skill);
|
{
|
||||||
|
Log.Out(Logs::Detail, Logs::Combat, "Fatal blow dealt by %s with %d damage, spell %d, skill %d",
|
||||||
|
((killer_mob) ? (killer_mob->GetName()) : ("[nullptr]")), damage, spell, attack_skill);
|
||||||
|
|
||||||
Mob *oos = nullptr;
|
Mob *oos = nullptr;
|
||||||
if(killer_mob) {
|
if (killer_mob) {
|
||||||
oos = killer_mob->GetOwnerOrSelf();
|
oos = killer_mob->GetOwnerOrSelf();
|
||||||
|
|
||||||
char buffer[48] = { 0 };
|
char buffer[48] = { 0 };
|
||||||
snprintf(buffer, 47, "%d %d %d %d", killer_mob ? killer_mob->GetID() : 0, damage, spell, static_cast<int>(attack_skill));
|
snprintf(buffer, 47, "%d %d %d %d", killer_mob->GetID(), damage, spell, static_cast<int>(attack_skill));
|
||||||
if(parse->EventNPC(EVENT_DEATH, this, oos, buffer, 0) != 0)
|
|
||||||
{
|
if (parse->EventNPC(EVENT_DEATH, this, oos, buffer, 0) != 0) {
|
||||||
if(GetHP() < 0) {
|
if (GetHP() < 0) {
|
||||||
SetHP(0);
|
SetHP(0);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(killer_mob && killer_mob->IsClient() && (spell != SPELL_UNKNOWN) && damage > 0) {
|
if (killer_mob->IsClient() && (spell != SPELL_UNKNOWN) && damage > 0) {
|
||||||
char val1[20]={0};
|
char val1[20] = { 0 };
|
||||||
entity_list.MessageClose_StringID(this, false, 100, MT_NonMelee, HIT_NON_MELEE,
|
entity_list.MessageClose_StringID(this, false, 100, MT_NonMelee, HIT_NON_MELEE,
|
||||||
killer_mob->GetCleanName(), GetCleanName(), ConvertArray(damage, val1));
|
killer_mob->GetCleanName(), GetCleanName(), ConvertArray(damage, val1));
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
char buffer[48] = { 0 };
|
char buffer[48] = { 0 };
|
||||||
snprintf(buffer, 47, "%d %d %d %d", killer_mob ? killer_mob->GetID() : 0, damage, spell, static_cast<int>(attack_skill));
|
snprintf(buffer, 47, "%d %d %d %d", 0, damage, spell, static_cast<int>(attack_skill));
|
||||||
if(parse->EventNPC(EVENT_DEATH, this, nullptr, buffer, 0) != 0)
|
|
||||||
{
|
if (parse->EventNPC(EVENT_DEATH, this, nullptr, buffer, 0) != 0) {
|
||||||
if(GetHP() < 0) {
|
if (GetHP() < 0) {
|
||||||
SetHP(0);
|
SetHP(0);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsEngaged())
|
if (IsEngaged()) {
|
||||||
{
|
|
||||||
zone->DelAggroMob();
|
zone->DelAggroMob();
|
||||||
Log.Out(Logs::Detail, Logs::Attack, "%s Mobs currently Aggro %i", __FUNCTION__, zone->MobsAggroCount());
|
Log.Out(Logs::Detail, Logs::Attack, "%s Mobs currently Aggro %i", __FUNCTION__, zone->MobsAggroCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
SetHP(0);
|
SetHP(0);
|
||||||
SetPet(0);
|
SetPet(0);
|
||||||
|
|
||||||
if (GetSwarmOwner()){
|
if (GetSwarmOwner()) {
|
||||||
Mob* owner = entity_list.GetMobID(GetSwarmOwner());
|
Mob* owner = entity_list.GetMobID(GetSwarmOwner());
|
||||||
if (owner)
|
if (owner)
|
||||||
owner->SetTempPetCount(owner->GetTempPetCount() - 1);
|
owner->SetTempPetCount(owner->GetTempPetCount() - 1);
|
||||||
@ -1927,14 +1929,14 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac
|
|||||||
|
|
||||||
entity_list.RemoveFromTargets(this, p_depop);
|
entity_list.RemoveFromTargets(this, p_depop);
|
||||||
|
|
||||||
if(p_depop == true)
|
if (p_depop == true)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
HasAISpellEffects = false;
|
HasAISpellEffects = false;
|
||||||
BuffFadeAll();
|
BuffFadeAll();
|
||||||
uint8 killed_level = GetLevel();
|
uint8 killed_level = GetLevel();
|
||||||
|
|
||||||
EQApplicationPacket* app= new EQApplicationPacket(OP_Death,sizeof(Death_Struct));
|
EQApplicationPacket* app = new EQApplicationPacket(OP_Death, sizeof(Death_Struct));
|
||||||
Death_Struct* d = (Death_Struct*)app->pBuffer;
|
Death_Struct* d = (Death_Struct*)app->pBuffer;
|
||||||
d->spawn_id = GetID();
|
d->spawn_id = GetID();
|
||||||
d->killer_id = killer_mob ? killer_mob->GetID() : 0;
|
d->killer_id = killer_mob ? killer_mob->GetID() : 0;
|
||||||
@ -1945,55 +1947,49 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac
|
|||||||
app->priority = 6;
|
app->priority = 6;
|
||||||
entity_list.QueueClients(killer_mob, app, false);
|
entity_list.QueueClients(killer_mob, app, false);
|
||||||
|
|
||||||
if(respawn2) {
|
safe_delete(app);
|
||||||
|
|
||||||
|
if (respawn2) {
|
||||||
respawn2->DeathReset(1);
|
respawn2->DeathReset(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (killer_mob) {
|
if (killer_mob && GetClass() != LDON_TREASURE)
|
||||||
if(GetClass() != LDON_TREASURE)
|
|
||||||
hate_list.AddEntToHateList(killer_mob, damage);
|
hate_list.AddEntToHateList(killer_mob, damage);
|
||||||
}
|
|
||||||
|
|
||||||
safe_delete(app);
|
|
||||||
|
|
||||||
Mob *give_exp = hate_list.GetDamageTopOnHateList(this);
|
Mob *give_exp = hate_list.GetDamageTopOnHateList(this);
|
||||||
|
|
||||||
if(give_exp == nullptr)
|
if (give_exp == nullptr)
|
||||||
give_exp = killer;
|
give_exp = killer;
|
||||||
|
|
||||||
if(give_exp && give_exp->HasOwner()) {
|
if (give_exp && give_exp->HasOwner()) {
|
||||||
|
|
||||||
bool ownerInGroup = false;
|
bool ownerInGroup = false;
|
||||||
if((give_exp->HasGroup() && give_exp->GetGroup()->IsGroupMember(give_exp->GetUltimateOwner()))
|
if ((give_exp->HasGroup() && give_exp->GetGroup()->IsGroupMember(give_exp->GetUltimateOwner()))
|
||||||
|| (give_exp->IsPet() && (give_exp->GetOwner()->IsClient()
|
|| (give_exp->IsPet() && (give_exp->GetOwner()->IsClient()
|
||||||
|| ( give_exp->GetOwner()->HasGroup() && give_exp->GetOwner()->GetGroup()->IsGroupMember(give_exp->GetOwner()->GetUltimateOwner())))))
|
|| (give_exp->GetOwner()->HasGroup() && give_exp->GetOwner()->GetGroup()->IsGroupMember(give_exp->GetOwner()->GetUltimateOwner())))))
|
||||||
ownerInGroup = true;
|
ownerInGroup = true;
|
||||||
|
|
||||||
give_exp = give_exp->GetUltimateOwner();
|
give_exp = give_exp->GetUltimateOwner();
|
||||||
|
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
if(!RuleB(Bots, BotGroupXP) && !ownerInGroup) {
|
if (!RuleB(Bots, BotGroupXP) && !ownerInGroup) {
|
||||||
give_exp = nullptr;
|
give_exp = nullptr;
|
||||||
}
|
}
|
||||||
#endif //BOTS
|
#endif //BOTS
|
||||||
}
|
}
|
||||||
|
|
||||||
if(give_exp && give_exp->IsTempPet() && give_exp->IsPetOwnerClient()) {
|
if (give_exp && give_exp->IsTempPet() && give_exp->IsPetOwnerClient()) {
|
||||||
|
if (give_exp->IsNPC() && give_exp->CastToNPC()->GetSwarmOwner()) {
|
||||||
if (give_exp->IsNPC() && give_exp->CastToNPC()->GetSwarmOwner()){
|
Mob* temp_owner = entity_list.GetMobID(give_exp->CastToNPC()->GetSwarmOwner());
|
||||||
Mob* temp_owner = nullptr;
|
|
||||||
temp_owner = entity_list.GetMobID(give_exp->CastToNPC()->GetSwarmOwner());
|
|
||||||
|
|
||||||
if (temp_owner)
|
if (temp_owner)
|
||||||
give_exp = temp_owner;
|
give_exp = temp_owner;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int PlayerCount = 0; // QueryServ Player Counting
|
int PlayerCount = 0; // QueryServ Player Counting
|
||||||
|
|
||||||
Client *give_exp_client = nullptr;
|
Client *give_exp_client = nullptr;
|
||||||
if(give_exp && give_exp->IsClient())
|
if (give_exp && give_exp->IsClient())
|
||||||
give_exp_client = give_exp->CastToClient();
|
give_exp_client = give_exp->CastToClient();
|
||||||
|
|
||||||
//do faction hits even if we are a merchant, so long as a player killed us
|
//do faction hits even if we are a merchant, so long as a player killed us
|
||||||
@ -2001,43 +1997,43 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac
|
|||||||
hate_list.DoFactionHits(GetNPCFactionID());
|
hate_list.DoFactionHits(GetNPCFactionID());
|
||||||
|
|
||||||
bool IsLdonTreasure = (this->GetClass() == LDON_TREASURE);
|
bool IsLdonTreasure = (this->GetClass() == LDON_TREASURE);
|
||||||
if (give_exp_client && !IsCorpse())
|
|
||||||
{
|
if (give_exp_client && !IsCorpse()) {
|
||||||
Group *kg = entity_list.GetGroupByClient(give_exp_client);
|
Group *kg = entity_list.GetGroupByClient(give_exp_client);
|
||||||
Raid *kr = entity_list.GetRaidByClient(give_exp_client);
|
Raid *kr = entity_list.GetRaidByClient(give_exp_client);
|
||||||
|
|
||||||
int32 finalxp = EXP_FORMULA;
|
int32 finalxp = EXP_FORMULA;
|
||||||
finalxp = give_exp_client->mod_client_xp(finalxp, this);
|
finalxp = give_exp_client->mod_client_xp(finalxp, this);
|
||||||
|
|
||||||
if(kr)
|
if (kr) {
|
||||||
{
|
if (!IsLdonTreasure && MerchantType == 0) {
|
||||||
if(!IsLdonTreasure && MerchantType == 0) {
|
|
||||||
kr->SplitExp((finalxp), this);
|
kr->SplitExp((finalxp), this);
|
||||||
if(killer_mob && (kr->IsRaidMember(killer_mob->GetName()) || kr->IsRaidMember(killer_mob->GetUltimateOwner()->GetName())))
|
if (killer_mob && (kr->IsRaidMember(killer_mob->GetName()) || kr->IsRaidMember(killer_mob->GetUltimateOwner()->GetName())))
|
||||||
killer_mob->TrySpellOnKill(killed_level,spell);
|
killer_mob->TrySpellOnKill(killed_level, spell);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send the EVENT_KILLED_MERIT event for all raid members */
|
/* Send the EVENT_KILLED_MERIT event for all raid members */
|
||||||
for (int i = 0; i < MAX_RAID_MEMBERS; i++) {
|
for (int i = 0; i < MAX_RAID_MEMBERS; i++) {
|
||||||
if (kr->members[i].member != nullptr && kr->members[i].member->IsClient()) { // If Group Member is Client
|
if (kr->members[i].member != nullptr && kr->members[i].member->IsClient()) { // If Group Member is Client
|
||||||
Client *c = kr->members[i].member;
|
Client *c = kr->members[i].member;
|
||||||
parse->EventNPC(EVENT_KILLED_MERIT, this, c, "killed", 0);
|
parse->EventNPC(EVENT_KILLED_MERIT, this, c, "killed", 0);
|
||||||
|
|
||||||
if(RuleB(NPC, EnableMeritBasedFaction))
|
if (RuleB(NPC, EnableMeritBasedFaction))
|
||||||
c->SetFactionLevel(c->CharacterID(), GetNPCFactionID(), c->GetBaseClass(), c->GetBaseRace(), c->GetDeity());
|
c->SetFactionLevel(c->CharacterID(), GetNPCFactionID(), c->GetBaseClass(), c->GetBaseRace(), c->GetDeity());
|
||||||
|
|
||||||
mod_npc_killed_merit(kr->members[i].member);
|
mod_npc_killed_merit(kr->members[i].member);
|
||||||
|
|
||||||
if(RuleB(TaskSystem, EnableTaskSystem))
|
if (RuleB(TaskSystem, EnableTaskSystem))
|
||||||
kr->members[i].member->UpdateTasksOnKill(GetNPCTypeID());
|
kr->members[i].member->UpdateTasksOnKill(GetNPCTypeID());
|
||||||
PlayerCount++;
|
PlayerCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryServ Logging - Raid Kills
|
// QueryServ Logging - Raid Kills
|
||||||
if(RuleB(QueryServ, PlayerLogNPCKills)){
|
if (RuleB(QueryServ, PlayerLogNPCKills)) {
|
||||||
ServerPacket* pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * PlayerCount));
|
ServerPacket* pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * PlayerCount));
|
||||||
PlayerCount = 0;
|
PlayerCount = 0;
|
||||||
QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*) pack->pBuffer;
|
QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer;
|
||||||
QS->s1.NPCID = this->GetNPCTypeID();
|
QS->s1.NPCID = this->GetNPCTypeID();
|
||||||
QS->s1.ZoneID = this->GetZoneID();
|
QS->s1.ZoneID = this->GetZoneID();
|
||||||
QS->s1.Type = 2; // Raid Fight
|
QS->s1.Type = 2; // Raid Fight
|
||||||
@ -2054,13 +2050,13 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac
|
|||||||
// End QueryServ Logging
|
// End QueryServ Logging
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (give_exp_client->IsGrouped() && kg != nullptr)
|
else if (give_exp_client->IsGrouped() && kg != nullptr) {
|
||||||
{
|
if (!IsLdonTreasure && MerchantType == 0) {
|
||||||
if(!IsLdonTreasure && MerchantType == 0) {
|
|
||||||
kg->SplitExp((finalxp), this);
|
kg->SplitExp((finalxp), this);
|
||||||
if(killer_mob && (kg->IsGroupMember(killer_mob->GetName()) || kg->IsGroupMember(killer_mob->GetUltimateOwner()->GetName())))
|
if (killer_mob && (kg->IsGroupMember(killer_mob->GetName()) || kg->IsGroupMember(killer_mob->GetUltimateOwner()->GetName())))
|
||||||
killer_mob->TrySpellOnKill(killed_level,spell);
|
killer_mob->TrySpellOnKill(killed_level, spell);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send the EVENT_KILLED_MERIT event and update kill tasks
|
/* Send the EVENT_KILLED_MERIT event and update kill tasks
|
||||||
* for all group members */
|
* for all group members */
|
||||||
for (int i = 0; i < MAX_GROUP_MEMBERS; i++) {
|
for (int i = 0; i < MAX_GROUP_MEMBERS; i++) {
|
||||||
@ -2068,12 +2064,12 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac
|
|||||||
Client *c = kg->members[i]->CastToClient();
|
Client *c = kg->members[i]->CastToClient();
|
||||||
parse->EventNPC(EVENT_KILLED_MERIT, this, c, "killed", 0);
|
parse->EventNPC(EVENT_KILLED_MERIT, this, c, "killed", 0);
|
||||||
|
|
||||||
if(RuleB(NPC, EnableMeritBasedFaction))
|
if (RuleB(NPC, EnableMeritBasedFaction))
|
||||||
c->SetFactionLevel(c->CharacterID(), GetNPCFactionID(), c->GetBaseClass(), c->GetBaseRace(), c->GetDeity());
|
c->SetFactionLevel(c->CharacterID(), GetNPCFactionID(), c->GetBaseClass(), c->GetBaseRace(), c->GetDeity());
|
||||||
|
|
||||||
mod_npc_killed_merit(c);
|
mod_npc_killed_merit(c);
|
||||||
|
|
||||||
if(RuleB(TaskSystem, EnableTaskSystem))
|
if (RuleB(TaskSystem, EnableTaskSystem))
|
||||||
c->UpdateTasksOnKill(GetNPCTypeID());
|
c->UpdateTasksOnKill(GetNPCTypeID());
|
||||||
|
|
||||||
PlayerCount++;
|
PlayerCount++;
|
||||||
@ -2081,10 +2077,10 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac
|
|||||||
}
|
}
|
||||||
|
|
||||||
// QueryServ Logging - Group Kills
|
// QueryServ Logging - Group Kills
|
||||||
if(RuleB(QueryServ, PlayerLogNPCKills)){
|
if (RuleB(QueryServ, PlayerLogNPCKills)) {
|
||||||
ServerPacket* pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * PlayerCount));
|
ServerPacket* pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * PlayerCount));
|
||||||
PlayerCount = 0;
|
PlayerCount = 0;
|
||||||
QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*) pack->pBuffer;
|
QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer;
|
||||||
QS->s1.NPCID = this->GetNPCTypeID();
|
QS->s1.NPCID = this->GetNPCTypeID();
|
||||||
QS->s1.ZoneID = this->GetZoneID();
|
QS->s1.ZoneID = this->GetZoneID();
|
||||||
QS->s1.Type = 1; // Group Fight
|
QS->s1.Type = 1; // Group Fight
|
||||||
@ -2100,36 +2096,34 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac
|
|||||||
}
|
}
|
||||||
// End QueryServ Logging
|
// End QueryServ Logging
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
if (!IsLdonTreasure && MerchantType == 0) {
|
||||||
if(!IsLdonTreasure && MerchantType == 0) {
|
|
||||||
int conlevel = give_exp->GetLevelCon(GetLevel());
|
int conlevel = give_exp->GetLevelCon(GetLevel());
|
||||||
if (conlevel != CON_GREEN)
|
if (conlevel != CON_GREEN) {
|
||||||
{
|
if (!GetOwner() || (GetOwner() && !GetOwner()->IsClient())) {
|
||||||
if(!GetOwner() || (GetOwner() && !GetOwner()->IsClient()))
|
|
||||||
{
|
|
||||||
give_exp_client->AddEXP((finalxp), conlevel);
|
give_exp_client->AddEXP((finalxp), conlevel);
|
||||||
if(killer_mob && (killer_mob->GetID() == give_exp_client->GetID() || killer_mob->GetUltimateOwner()->GetID() == give_exp_client->GetID()))
|
if (killer_mob && (killer_mob->GetID() == give_exp_client->GetID() || killer_mob->GetUltimateOwner()->GetID() == give_exp_client->GetID()))
|
||||||
killer_mob->TrySpellOnKill(killed_level,spell);
|
killer_mob->TrySpellOnKill(killed_level, spell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send the EVENT_KILLED_MERIT event */
|
/* Send the EVENT_KILLED_MERIT event */
|
||||||
parse->EventNPC(EVENT_KILLED_MERIT, this, give_exp_client, "killed", 0);
|
parse->EventNPC(EVENT_KILLED_MERIT, this, give_exp_client, "killed", 0);
|
||||||
|
|
||||||
if(RuleB(NPC, EnableMeritBasedFaction))
|
if (RuleB(NPC, EnableMeritBasedFaction))
|
||||||
give_exp_client->SetFactionLevel(give_exp_client->CharacterID(), GetNPCFactionID(), give_exp_client->GetBaseClass(),
|
give_exp_client->SetFactionLevel(give_exp_client->CharacterID(), GetNPCFactionID(), give_exp_client->GetBaseClass(),
|
||||||
give_exp_client->GetBaseRace(), give_exp_client->GetDeity());
|
give_exp_client->GetBaseRace(), give_exp_client->GetDeity());
|
||||||
|
|
||||||
mod_npc_killed_merit(give_exp_client);
|
mod_npc_killed_merit(give_exp_client);
|
||||||
|
|
||||||
if(RuleB(TaskSystem, EnableTaskSystem))
|
if (RuleB(TaskSystem, EnableTaskSystem))
|
||||||
give_exp_client->UpdateTasksOnKill(GetNPCTypeID());
|
give_exp_client->UpdateTasksOnKill(GetNPCTypeID());
|
||||||
|
|
||||||
// QueryServ Logging - Solo
|
// QueryServ Logging - Solo
|
||||||
if(RuleB(QueryServ, PlayerLogNPCKills)){
|
if (RuleB(QueryServ, PlayerLogNPCKills)) {
|
||||||
ServerPacket* pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * 1));
|
ServerPacket* pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * 1));
|
||||||
QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*) pack->pBuffer;
|
QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer;
|
||||||
QS->s1.NPCID = this->GetNPCTypeID();
|
QS->s1.NPCID = this->GetNPCTypeID();
|
||||||
QS->s1.ZoneID = this->GetZoneID();
|
QS->s1.ZoneID = this->GetZoneID();
|
||||||
QS->s1.Type = 0; // Solo Fight
|
QS->s1.Type = 0; // Solo Fight
|
||||||
@ -2144,74 +2138,73 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!HasOwner() && !IsMerc() && class_ != MERCHANT && class_ != ADVENTUREMERCHANT && !GetSwarmInfo()
|
if (!HasOwner() && !IsMerc() && class_ != MERCHANT && class_ != ADVENTUREMERCHANT && !GetSwarmInfo()
|
||||||
&& MerchantType == 0 && killer && (killer->IsClient() || (killer->HasOwner() && killer->GetUltimateOwner()->IsClient()) ||
|
&& MerchantType == 0 && ((killer && (killer->IsClient() || (killer->HasOwner() && killer->GetUltimateOwner()->IsClient()) ||
|
||||||
(killer->IsNPC() && killer->CastToNPC()->GetSwarmInfo() && killer->CastToNPC()->GetSwarmInfo()->GetOwner() && killer->CastToNPC()->GetSwarmInfo()->GetOwner()->IsClient())))
|
(killer->IsNPC() && killer->CastToNPC()->GetSwarmInfo() && killer->CastToNPC()->GetSwarmInfo()->GetOwner() && killer->CastToNPC()->GetSwarmInfo()->GetOwner()->IsClient())))
|
||||||
|
|| (killer_mob && IsLdonTreasure)))
|
||||||
{
|
{
|
||||||
if(killer != 0)
|
if (killer != 0) {
|
||||||
{
|
if (killer->GetOwner() != 0 && killer->GetOwner()->IsClient())
|
||||||
if(killer->GetOwner() != 0 && killer->GetOwner()->IsClient())
|
|
||||||
killer = killer->GetOwner();
|
killer = killer->GetOwner();
|
||||||
|
|
||||||
if(!killer->CastToClient()->GetGM() && killer->IsClient())
|
if (killer->IsClient() && !killer->CastToClient()->GetGM())
|
||||||
this->CheckMinMaxLevel(killer);
|
this->CheckMinMaxLevel(killer);
|
||||||
}
|
}
|
||||||
|
|
||||||
entity_list.RemoveFromAutoXTargets(this);
|
entity_list.RemoveFromAutoXTargets(this);
|
||||||
uint16 emoteid = this->GetEmoteID();
|
uint16 emoteid = this->GetEmoteID();
|
||||||
Corpse* corpse = new Corpse(this, &itemlist, GetNPCTypeID(), &NPCTypedata,level>54?RuleI(NPC,MajorNPCCorpseDecayTimeMS):RuleI(NPC,MinorNPCCorpseDecayTimeMS));
|
Corpse* corpse = new Corpse(this, &itemlist, GetNPCTypeID(), &NPCTypedata, level>54 ? RuleI(NPC, MajorNPCCorpseDecayTimeMS) : RuleI(NPC, MinorNPCCorpseDecayTimeMS));
|
||||||
entity_list.LimitRemoveNPC(this);
|
entity_list.LimitRemoveNPC(this);
|
||||||
entity_list.AddCorpse(corpse, GetID());
|
entity_list.AddCorpse(corpse, GetID());
|
||||||
|
|
||||||
entity_list.UnMarkNPC(GetID());
|
entity_list.UnMarkNPC(GetID());
|
||||||
entity_list.RemoveNPC(GetID());
|
entity_list.RemoveNPC(GetID());
|
||||||
this->SetID(0);
|
this->SetID(0);
|
||||||
if(killer != 0 && emoteid != 0)
|
|
||||||
|
if (killer != 0 && emoteid != 0)
|
||||||
corpse->CastToNPC()->DoNPCEmote(AFTERDEATH, emoteid);
|
corpse->CastToNPC()->DoNPCEmote(AFTERDEATH, emoteid);
|
||||||
if(killer != 0 && killer->IsClient()) {
|
if (killer != 0 && killer->IsClient()) {
|
||||||
corpse->AllowPlayerLoot(killer, 0);
|
corpse->AllowPlayerLoot(killer, 0);
|
||||||
if(killer->IsGrouped()) {
|
if (killer->IsGrouped()) {
|
||||||
Group* group = entity_list.GetGroupByClient(killer->CastToClient());
|
Group* group = entity_list.GetGroupByClient(killer->CastToClient());
|
||||||
if(group != 0) {
|
if (group != 0) {
|
||||||
for(int i=0;i<6;i++) { // Doesnt work right, needs work
|
for (int i = 0; i<6; i++) { // Doesnt work right, needs work
|
||||||
if(group->members[i] != nullptr) {
|
if (group->members[i] != nullptr) {
|
||||||
corpse->AllowPlayerLoot(group->members[i],i);
|
corpse->AllowPlayerLoot(group->members[i], i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(killer->IsRaidGrouped()){
|
else if (killer->IsRaidGrouped()) {
|
||||||
Raid* r = entity_list.GetRaidByClient(killer->CastToClient());
|
Raid* r = entity_list.GetRaidByClient(killer->CastToClient());
|
||||||
if(r){
|
if (r) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(int x = 0; x < MAX_RAID_MEMBERS; x++)
|
for (int x = 0; x < MAX_RAID_MEMBERS; x++) {
|
||||||
{
|
switch (r->GetLootType()) {
|
||||||
switch(r->GetLootType())
|
|
||||||
{
|
|
||||||
case 0:
|
case 0:
|
||||||
case 1:
|
case 1:
|
||||||
if(r->members[x].member && r->members[x].IsRaidLeader){
|
if (r->members[x].member && r->members[x].IsRaidLeader) {
|
||||||
corpse->AllowPlayerLoot(r->members[x].member, i);
|
corpse->AllowPlayerLoot(r->members[x].member, i);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if(r->members[x].member && r->members[x].IsRaidLeader){
|
if (r->members[x].member && r->members[x].IsRaidLeader) {
|
||||||
corpse->AllowPlayerLoot(r->members[x].member, i);
|
corpse->AllowPlayerLoot(r->members[x].member, i);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
else if(r->members[x].member && r->members[x].IsGroupLeader){
|
else if (r->members[x].member && r->members[x].IsGroupLeader) {
|
||||||
corpse->AllowPlayerLoot(r->members[x].member, i);
|
corpse->AllowPlayerLoot(r->members[x].member, i);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if(r->members[x].member && r->members[x].IsLooter){
|
if (r->members[x].member && r->members[x].IsLooter) {
|
||||||
corpse->AllowPlayerLoot(r->members[x].member, i);
|
corpse->AllowPlayerLoot(r->members[x].member, i);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
if(r->members[x].member)
|
if (r->members[x].member) {
|
||||||
{
|
|
||||||
corpse->AllowPlayerLoot(r->members[x].member, i);
|
corpse->AllowPlayerLoot(r->members[x].member, i);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@ -2221,42 +2214,42 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (killer_mob && IsLdonTreasure) {
|
||||||
|
auto u_owner = killer_mob->GetUltimateOwner();
|
||||||
|
if (u_owner->IsClient())
|
||||||
|
corpse->AllowPlayerLoot(u_owner, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if(zone && zone->adv_data)
|
if (zone && zone->adv_data) {
|
||||||
{
|
|
||||||
ServerZoneAdventureDataReply_Struct *sr = (ServerZoneAdventureDataReply_Struct*)zone->adv_data;
|
ServerZoneAdventureDataReply_Struct *sr = (ServerZoneAdventureDataReply_Struct*)zone->adv_data;
|
||||||
if(sr->type == Adventure_Kill)
|
if (sr->type == Adventure_Kill) {
|
||||||
{
|
|
||||||
zone->DoAdventureCountIncrease();
|
zone->DoAdventureCountIncrease();
|
||||||
}
|
}
|
||||||
else if(sr->type == Adventure_Assassinate)
|
else if (sr->type == Adventure_Assassinate) {
|
||||||
{
|
if (sr->data_id == GetNPCTypeID()) {
|
||||||
if(sr->data_id == GetNPCTypeID())
|
|
||||||
{
|
|
||||||
zone->DoAdventureCountIncrease();
|
zone->DoAdventureCountIncrease();
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
zone->DoAdventureAssassinationCountIncrease();
|
zone->DoAdventureAssassinationCountIncrease();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
entity_list.RemoveFromXTargets(this);
|
entity_list.RemoveFromXTargets(this);
|
||||||
|
}
|
||||||
|
|
||||||
// Parse quests even if we're killed by an NPC
|
// Parse quests even if we're killed by an NPC
|
||||||
if(oos) {
|
if (oos) {
|
||||||
mod_npc_killed(oos);
|
mod_npc_killed(oos);
|
||||||
|
|
||||||
uint16 emoteid = this->GetEmoteID();
|
uint16 emoteid = this->GetEmoteID();
|
||||||
if(emoteid != 0)
|
if (emoteid != 0)
|
||||||
this->DoNPCEmote(ONDEATH, emoteid);
|
this->DoNPCEmote(ONDEATH, emoteid);
|
||||||
if(oos->IsNPC())
|
if (oos->IsNPC()) {
|
||||||
{
|
|
||||||
parse->EventNPC(EVENT_NPC_SLAY, oos->CastToNPC(), this, "", 0);
|
parse->EventNPC(EVENT_NPC_SLAY, oos->CastToNPC(), this, "", 0);
|
||||||
uint16 emoteid = oos->GetEmoteID();
|
uint16 emoteid = oos->GetEmoteID();
|
||||||
if(emoteid != 0)
|
if (emoteid != 0)
|
||||||
oos->CastToNPC()->DoNPCEmote(KILLEDNPC, emoteid);
|
oos->CastToNPC()->DoNPCEmote(KILLEDNPC, emoteid);
|
||||||
killer_mob->TrySpellOnKill(killed_level, spell);
|
killer_mob->TrySpellOnKill(killed_level, spell);
|
||||||
}
|
}
|
||||||
@ -2264,7 +2257,8 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac
|
|||||||
|
|
||||||
WipeHateList();
|
WipeHateList();
|
||||||
p_depop = true;
|
p_depop = true;
|
||||||
if(killer_mob && killer_mob->GetTarget() == this) //we can kill things without having them targeted
|
|
||||||
|
if (killer_mob && killer_mob->GetTarget() == this) //we can kill things without having them targeted
|
||||||
killer_mob->SetTarget(nullptr); //via AE effects and such..
|
killer_mob->SetTarget(nullptr); //via AE effects and such..
|
||||||
|
|
||||||
entity_list.UpdateFindableNPCState(this, true);
|
entity_list.UpdateFindableNPCState(this, true);
|
||||||
@ -2275,7 +2269,7 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac
|
|||||||
|
|
||||||
/* Zone controller process EVENT_DEATH_ZONE (Death events) */
|
/* Zone controller process EVENT_DEATH_ZONE (Death events) */
|
||||||
if (RuleB(Zone, UseZoneController)) {
|
if (RuleB(Zone, UseZoneController)) {
|
||||||
if (entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID) && this->GetNPCTypeID() != ZONE_CONTROLLER_NPC_ID){
|
if (entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID) && this->GetNPCTypeID() != ZONE_CONTROLLER_NPC_ID) {
|
||||||
char data_pass[100] = { 0 };
|
char data_pass[100] = { 0 };
|
||||||
snprintf(data_pass, 99, "%d %d %d %d %d", killer_mob ? killer_mob->GetID() : 0, damage, spell, static_cast<int>(attack_skill), this->GetNPCTypeID());
|
snprintf(data_pass, 99, "%d %d %d %d %d", killer_mob ? killer_mob->GetID() : 0, damage, spell, static_cast<int>(attack_skill), this->GetNPCTypeID());
|
||||||
parse->EventNPC(EVENT_DEATH_ZONE, entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID)->CastToNPC(), nullptr, data_pass, 0);
|
parse->EventNPC(EVENT_DEATH_ZONE, entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID)->CastToNPC(), nullptr, data_pass, 0);
|
||||||
|
|||||||
@ -144,12 +144,12 @@ void Client::CalcItemBonuses(StatBonuses* newbon) {
|
|||||||
SetTwoHanderEquipped(false);
|
SetTwoHanderEquipped(false);
|
||||||
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
//should not include 21 (SLOT_AMMO)
|
// Update: MainAmmo should only calc skill mods (TODO: Check for other cases)
|
||||||
for (i = MainCharm; i < MainAmmo; i++) {
|
for (i = MainCharm; i <= MainAmmo; i++) {
|
||||||
const ItemInst* inst = m_inv[i];
|
const ItemInst* inst = m_inv[i];
|
||||||
if(inst == 0)
|
if(inst == 0)
|
||||||
continue;
|
continue;
|
||||||
AddItemBonuses(inst, newbon);
|
AddItemBonuses(inst, newbon, false, false, 0, (i == MainAmmo));
|
||||||
|
|
||||||
//These are given special flags due to how often they are checked for various spell effects.
|
//These are given special flags due to how often they are checked for various spell effects.
|
||||||
const Item_Struct *item = inst->GetItem();
|
const Item_Struct *item = inst->GetItem();
|
||||||
@ -207,7 +207,7 @@ void Client::ProcessItemCaps()
|
|||||||
itembonuses.ATK = std::min(itembonuses.ATK, CalcItemATKCap());
|
itembonuses.ATK = std::min(itembonuses.ATK, CalcItemATKCap());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::AddItemBonuses(const ItemInst *inst, StatBonuses *newbon, bool isAug, bool isTribute, int rec_override)
|
void Client::AddItemBonuses(const ItemInst *inst, StatBonuses *newbon, bool isAug, bool isTribute, int rec_override, bool ammo_slot_item)
|
||||||
{
|
{
|
||||||
if (!inst || !inst->IsType(ItemClassCommon)) {
|
if (!inst || !inst->IsType(ItemClassCommon)) {
|
||||||
return;
|
return;
|
||||||
@ -231,6 +231,8 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses *newbon, bool isAu
|
|||||||
// So there isn't a very nice way to get the real rec level from the aug's inst, so we just pass it in, only
|
// So there isn't a very nice way to get the real rec level from the aug's inst, so we just pass it in, only
|
||||||
// used for augs
|
// used for augs
|
||||||
auto rec_level = isAug ? rec_override : inst->GetItemRecommendedLevel(true);
|
auto rec_level = isAug ? rec_override : inst->GetItemRecommendedLevel(true);
|
||||||
|
|
||||||
|
if (!ammo_slot_item) {
|
||||||
if (GetLevel() >= rec_level) {
|
if (GetLevel() >= rec_level) {
|
||||||
newbon->AC += item->AC;
|
newbon->AC += item->AC;
|
||||||
newbon->HP += item->HP;
|
newbon->HP += item->HP;
|
||||||
@ -280,7 +282,8 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses *newbon, bool isAu
|
|||||||
newbon->HeroicDR += item->HeroicDR;
|
newbon->HeroicDR += item->HeroicDR;
|
||||||
newbon->HeroicCorrup += item->HeroicSVCorrup;
|
newbon->HeroicCorrup += item->HeroicSVCorrup;
|
||||||
|
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
int lvl = GetLevel();
|
int lvl = GetLevel();
|
||||||
|
|
||||||
newbon->AC += CalcRecommendedLevelBonus(lvl, rec_level, item->AC);
|
newbon->AC += CalcRecommendedLevelBonus(lvl, rec_level, item->AC);
|
||||||
@ -436,7 +439,6 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses *newbon, bool isAu
|
|||||||
|
|
||||||
switch (item->BardType) {
|
switch (item->BardType) {
|
||||||
case 51: /* All (e.g. Singing Short Sword) */
|
case 51: /* All (e.g. Singing Short Sword) */
|
||||||
{
|
|
||||||
if (item->BardValue > newbon->singingMod)
|
if (item->BardValue > newbon->singingMod)
|
||||||
newbon->singingMod = item->BardValue;
|
newbon->singingMod = item->BardValue;
|
||||||
if (item->BardValue > newbon->brassMod)
|
if (item->BardValue > newbon->brassMod)
|
||||||
@ -448,73 +450,58 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses *newbon, bool isAu
|
|||||||
if (item->BardValue > newbon->windMod)
|
if (item->BardValue > newbon->windMod)
|
||||||
newbon->windMod = item->BardValue;
|
newbon->windMod = item->BardValue;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case 50: /* Singing */
|
case 50: /* Singing */
|
||||||
{
|
|
||||||
if (item->BardValue > newbon->singingMod)
|
if (item->BardValue > newbon->singingMod)
|
||||||
newbon->singingMod = item->BardValue;
|
newbon->singingMod = item->BardValue;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case 23: /* Wind */
|
case 23: /* Wind */
|
||||||
{
|
|
||||||
if (item->BardValue > newbon->windMod)
|
if (item->BardValue > newbon->windMod)
|
||||||
newbon->windMod = item->BardValue;
|
newbon->windMod = item->BardValue;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case 24: /* stringed */
|
case 24: /* stringed */
|
||||||
{
|
|
||||||
if (item->BardValue > newbon->stringedMod)
|
if (item->BardValue > newbon->stringedMod)
|
||||||
newbon->stringedMod = item->BardValue;
|
newbon->stringedMod = item->BardValue;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case 25: /* brass */
|
case 25: /* brass */
|
||||||
{
|
|
||||||
if (item->BardValue > newbon->brassMod)
|
if (item->BardValue > newbon->brassMod)
|
||||||
newbon->brassMod = item->BardValue;
|
newbon->brassMod = item->BardValue;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case 26: /* Percussion */
|
case 26: /* Percussion */
|
||||||
{
|
|
||||||
if (item->BardValue > newbon->percussionMod)
|
if (item->BardValue > newbon->percussionMod)
|
||||||
newbon->percussionMod = item->BardValue;
|
newbon->percussionMod = item->BardValue;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (item->SkillModValue != 0 && item->SkillModType <= HIGHEST_SKILL) {
|
|
||||||
if ((item->SkillModValue > 0 && newbon->skillmod[item->SkillModType] < item->SkillModValue) ||
|
|
||||||
(item->SkillModValue < 0 && newbon->skillmod[item->SkillModType] > item->SkillModValue)) {
|
|
||||||
newbon->skillmod[item->SkillModType] = item->SkillModValue;
|
|
||||||
newbon->skillmodmax[item->SkillModType] = item->SkillModMax;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add Item Faction Mods
|
// Add Item Faction Mods
|
||||||
if (item->FactionMod1) {
|
if (item->FactionMod1) {
|
||||||
if (item->FactionAmt1 > 0 && item->FactionAmt1 > GetItemFactionBonus(item->FactionMod1)) {
|
if (item->FactionAmt1 > 0 && item->FactionAmt1 > GetItemFactionBonus(item->FactionMod1)) {
|
||||||
AddItemFactionBonus(item->FactionMod1, item->FactionAmt1);
|
AddItemFactionBonus(item->FactionMod1, item->FactionAmt1);
|
||||||
} else if (item->FactionAmt1 < 0 && item->FactionAmt1 < GetItemFactionBonus(item->FactionMod1)) {
|
}
|
||||||
|
else if (item->FactionAmt1 < 0 && item->FactionAmt1 < GetItemFactionBonus(item->FactionMod1)) {
|
||||||
AddItemFactionBonus(item->FactionMod1, item->FactionAmt1);
|
AddItemFactionBonus(item->FactionMod1, item->FactionAmt1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (item->FactionMod2) {
|
if (item->FactionMod2) {
|
||||||
if (item->FactionAmt2 > 0 && item->FactionAmt2 > GetItemFactionBonus(item->FactionMod2)) {
|
if (item->FactionAmt2 > 0 && item->FactionAmt2 > GetItemFactionBonus(item->FactionMod2)) {
|
||||||
AddItemFactionBonus(item->FactionMod2, item->FactionAmt2);
|
AddItemFactionBonus(item->FactionMod2, item->FactionAmt2);
|
||||||
} else if (item->FactionAmt2 < 0 && item->FactionAmt2 < GetItemFactionBonus(item->FactionMod2)) {
|
}
|
||||||
|
else if (item->FactionAmt2 < 0 && item->FactionAmt2 < GetItemFactionBonus(item->FactionMod2)) {
|
||||||
AddItemFactionBonus(item->FactionMod2, item->FactionAmt2);
|
AddItemFactionBonus(item->FactionMod2, item->FactionAmt2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (item->FactionMod3) {
|
if (item->FactionMod3) {
|
||||||
if (item->FactionAmt3 > 0 && item->FactionAmt3 > GetItemFactionBonus(item->FactionMod3)) {
|
if (item->FactionAmt3 > 0 && item->FactionAmt3 > GetItemFactionBonus(item->FactionMod3)) {
|
||||||
AddItemFactionBonus(item->FactionMod3, item->FactionAmt3);
|
AddItemFactionBonus(item->FactionMod3, item->FactionAmt3);
|
||||||
} else if (item->FactionAmt3 < 0 && item->FactionAmt3 < GetItemFactionBonus(item->FactionMod3)) {
|
}
|
||||||
|
else if (item->FactionAmt3 < 0 && item->FactionAmt3 < GetItemFactionBonus(item->FactionMod3)) {
|
||||||
AddItemFactionBonus(item->FactionMod3, item->FactionAmt3);
|
AddItemFactionBonus(item->FactionMod3, item->FactionAmt3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (item->FactionMod4) {
|
if (item->FactionMod4) {
|
||||||
if (item->FactionAmt4 > 0 && item->FactionAmt4 > GetItemFactionBonus(item->FactionMod4)) {
|
if (item->FactionAmt4 > 0 && item->FactionAmt4 > GetItemFactionBonus(item->FactionMod4)) {
|
||||||
AddItemFactionBonus(item->FactionMod4, item->FactionAmt4);
|
AddItemFactionBonus(item->FactionMod4, item->FactionAmt4);
|
||||||
} else if (item->FactionAmt4 < 0 && item->FactionAmt4 < GetItemFactionBonus(item->FactionMod4)) {
|
}
|
||||||
|
else if (item->FactionAmt4 < 0 && item->FactionAmt4 < GetItemFactionBonus(item->FactionMod4)) {
|
||||||
AddItemFactionBonus(item->FactionMod4, item->FactionAmt4);
|
AddItemFactionBonus(item->FactionMod4, item->FactionAmt4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -526,10 +513,21 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses *newbon, bool isAu
|
|||||||
else
|
else
|
||||||
newbon->SkillDamageAmount[item->ExtraDmgSkill] += item->ExtraDmgAmt;
|
newbon->SkillDamageAmount[item->ExtraDmgSkill] += item->ExtraDmgAmt;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process when ammo_slot_item = true or false
|
||||||
|
if (item->SkillModValue != 0 && item->SkillModType <= HIGHEST_SKILL) {
|
||||||
|
if ((item->SkillModValue > 0 && newbon->skillmod[item->SkillModType] < item->SkillModValue) ||
|
||||||
|
(item->SkillModValue < 0 && newbon->skillmod[item->SkillModType] > item->SkillModValue)) {
|
||||||
|
|
||||||
|
newbon->skillmod[item->SkillModType] = item->SkillModValue;
|
||||||
|
newbon->skillmodmax[item->SkillModType] = item->SkillModMax;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!isAug) {
|
if (!isAug) {
|
||||||
for (int i = 0; i < EmuConstants::ITEM_COMMON_SIZE; i++)
|
for (int i = 0; i < EmuConstants::ITEM_COMMON_SIZE; i++)
|
||||||
AddItemBonuses(inst->GetAugment(i), newbon, true, false, rec_level);
|
AddItemBonuses(inst->GetAugment(i), newbon, true, false, rec_level, ammo_slot_item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -587,10 +587,9 @@ bool Client::Save(uint8 iCommitNow) {
|
|||||||
database.SaveCharacterCurrency(CharacterID(), &m_pp);
|
database.SaveCharacterCurrency(CharacterID(), &m_pp);
|
||||||
|
|
||||||
/* Save Current Bind Points */
|
/* Save Current Bind Points */
|
||||||
auto regularBindPosition = glm::vec4(m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, 0.0f);
|
for (int i = 0; i < 5; i++)
|
||||||
auto homeBindPosition = glm::vec4(m_pp.binds[4].x, m_pp.binds[4].y, m_pp.binds[4].z, 0.0f);
|
if (m_pp.binds[i].zoneId)
|
||||||
database.SaveCharacterBindPoint(CharacterID(), m_pp.binds[0].zoneId, m_pp.binds[0].instance_id, regularBindPosition, 0); /* Regular bind */
|
database.SaveCharacterBindPoint(CharacterID(), m_pp.binds[i], i);
|
||||||
database.SaveCharacterBindPoint(CharacterID(), m_pp.binds[4].zoneId, m_pp.binds[4].instance_id, homeBindPosition, 1); /* Home Bind */
|
|
||||||
|
|
||||||
/* Save Character Buffs */
|
/* Save Character Buffs */
|
||||||
database.SaveBuffs(this);
|
database.SaveBuffs(this);
|
||||||
|
|||||||
@ -582,8 +582,8 @@ public:
|
|||||||
|
|
||||||
void GoToBind(uint8 bindnum = 0);
|
void GoToBind(uint8 bindnum = 0);
|
||||||
void GoToSafeCoords(uint16 zone_id, uint16 instance_id);
|
void GoToSafeCoords(uint16 zone_id, uint16 instance_id);
|
||||||
void Gate();
|
void Gate(uint8 bindnum = 0);
|
||||||
void SetBindPoint(int to_zone = -1, int to_instance = 0, const glm::vec3& location = glm::vec3());
|
void SetBindPoint(int bind_num = 0, int to_zone = -1, int to_instance = 0, const glm::vec3& location = glm::vec3());
|
||||||
void SetStartZone(uint32 zoneid, float x = 0.0f, float y =0.0f, float z = 0.0f);
|
void SetStartZone(uint32 zoneid, float x = 0.0f, float y =0.0f, float z = 0.0f);
|
||||||
uint32 GetStartZone(void);
|
uint32 GetStartZone(void);
|
||||||
void MovePC(const char* zonename, float x, float y, float z, float heading, uint8 ignorerestrictions = 0, ZoneMode zm = ZoneSolicited);
|
void MovePC(const char* zonename, float x, float y, float z, float heading, uint8 ignorerestrictions = 0, ZoneMode zm = ZoneSolicited);
|
||||||
@ -1303,7 +1303,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
friend class Mob;
|
friend class Mob;
|
||||||
void CalcItemBonuses(StatBonuses* newbon);
|
void CalcItemBonuses(StatBonuses* newbon);
|
||||||
void AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug = false, bool isTribute = false, int rec_override = 0);
|
void AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug = false, bool isTribute = false, int rec_override = 0, bool ammo_slot_item = false);
|
||||||
void AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug = false);
|
void AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug = false);
|
||||||
int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat);
|
int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat);
|
||||||
void CalcEdibleBonuses(StatBonuses* newbon);
|
void CalcEdibleBonuses(StatBonuses* newbon);
|
||||||
|
|||||||
@ -232,27 +232,27 @@ void Lua_Client::SetBindPoint() {
|
|||||||
|
|
||||||
void Lua_Client::SetBindPoint(int to_zone) {
|
void Lua_Client::SetBindPoint(int to_zone) {
|
||||||
Lua_Safe_Call_Void();
|
Lua_Safe_Call_Void();
|
||||||
self->SetBindPoint(to_zone);
|
self->SetBindPoint(0, to_zone);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lua_Client::SetBindPoint(int to_zone, int to_instance) {
|
void Lua_Client::SetBindPoint(int to_zone, int to_instance) {
|
||||||
Lua_Safe_Call_Void();
|
Lua_Safe_Call_Void();
|
||||||
self->SetBindPoint(to_zone, to_instance);
|
self->SetBindPoint(0, to_zone, to_instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x) {
|
void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x) {
|
||||||
Lua_Safe_Call_Void();
|
Lua_Safe_Call_Void();
|
||||||
self->SetBindPoint(to_zone, to_instance, glm::vec3(new_x,0.0f,0.0f));
|
self->SetBindPoint(0, to_zone, to_instance, glm::vec3(new_x,0.0f,0.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x, float new_y) {
|
void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x, float new_y) {
|
||||||
Lua_Safe_Call_Void();
|
Lua_Safe_Call_Void();
|
||||||
self->SetBindPoint(to_zone, to_instance, glm::vec3(new_x, new_y, 0.0f));
|
self->SetBindPoint(0, to_zone, to_instance, glm::vec3(new_x, new_y, 0.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x, float new_y, float new_z) {
|
void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x, float new_y, float new_z) {
|
||||||
Lua_Safe_Call_Void();
|
Lua_Safe_Call_Void();
|
||||||
self->SetBindPoint(to_zone, to_instance, glm::vec3(new_x, new_y, new_z));
|
self->SetBindPoint(0, to_zone, to_instance, glm::vec3(new_x, new_y, new_z));
|
||||||
}
|
}
|
||||||
|
|
||||||
float Lua_Client::GetBindX() {
|
float Lua_Client::GetBindX() {
|
||||||
|
|||||||
@ -468,7 +468,7 @@ public:
|
|||||||
inline bool IsMoving() const { return moving; }
|
inline bool IsMoving() const { return moving; }
|
||||||
virtual void SetMoving(bool move) { moving = move; m_Delta = glm::vec4(); }
|
virtual void SetMoving(bool move) { moving = move; m_Delta = glm::vec4(); }
|
||||||
virtual void GoToBind(uint8 bindnum = 0) { }
|
virtual void GoToBind(uint8 bindnum = 0) { }
|
||||||
virtual void Gate();
|
virtual void Gate(uint8 bindnum = 0);
|
||||||
int GetWalkspeed() const { return(_GetWalkSpeed()); }
|
int GetWalkspeed() const { return(_GetWalkSpeed()); }
|
||||||
int GetRunspeed() const { return(_GetRunSpeed()); }
|
int GetRunspeed() const { return(_GetRunSpeed()); }
|
||||||
void SetCurrentSpeed(int in);
|
void SetCurrentSpeed(int in);
|
||||||
|
|||||||
227
zone/npc.cpp
227
zone/npc.cpp
@ -1425,13 +1425,13 @@ uint32 NPC::GetMaxDamage(uint8 tlevel)
|
|||||||
return dmg;
|
return dmg;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NPC::PickPocket(Client* thief) {
|
void NPC::PickPocket(Client* thief)
|
||||||
|
{
|
||||||
thief->CheckIncreaseSkill(SkillPickPockets, nullptr, 5);
|
thief->CheckIncreaseSkill(SkillPickPockets, nullptr, 5);
|
||||||
|
|
||||||
//make sure were allowed to targte them:
|
//make sure were allowed to target them:
|
||||||
int olevel = GetLevel();
|
int over_level = GetLevel();
|
||||||
if(olevel > (thief->GetLevel() + THIEF_PICKPOCKET_OVER)) {
|
if(over_level > (thief->GetLevel() + THIEF_PICKPOCKET_OVER)) {
|
||||||
thief->Message(13, "You are too inexperienced to pick pocket this target");
|
thief->Message(13, "You are too inexperienced to pick pocket this target");
|
||||||
thief->SendPickPocketResponse(this, 0, PickPocketFailed);
|
thief->SendPickPocketResponse(this, 0, PickPocketFailed);
|
||||||
//should we check aggro
|
//should we check aggro
|
||||||
@ -1447,150 +1447,109 @@ void NPC::PickPocket(Client* thief) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int steal_skill = thief->GetSkill(SkillPickPockets);
|
int steal_skill = thief->GetSkill(SkillPickPockets);
|
||||||
int stealchance = steal_skill*100/(5*olevel+5);
|
int steal_chance = steal_skill * 100 / (5 * over_level + 5);
|
||||||
ItemInst* inst = 0;
|
|
||||||
int x = 0;
|
|
||||||
int slot[50];
|
|
||||||
int steal_items[50];
|
|
||||||
int charges[50];
|
|
||||||
int money[4];
|
|
||||||
money[0] = GetPlatinum();
|
|
||||||
money[1] = GetGold();
|
|
||||||
money[2] = GetSilver();
|
|
||||||
money[3] = GetCopper();
|
|
||||||
if (steal_skill < 125)
|
|
||||||
money[0] = 0;
|
|
||||||
if (steal_skill < 60)
|
|
||||||
money[1] = 0;
|
|
||||||
memset(slot,0,50);
|
|
||||||
memset(steal_items,0,50);
|
|
||||||
memset(charges,0,50);
|
|
||||||
//Determine wheter to steal money or an item.
|
//Determine wheter to steal money or an item.
|
||||||
bool no_coin = ((money[0] + money[1] + money[2] + money[3]) == 0);
|
int money[6] = { 0, ((steal_skill >= 125) ? (GetPlatinum()) : (0)), ((steal_skill >= 60) ? (GetGold()) : (0)), GetSilver(), GetCopper(), 0 };
|
||||||
bool steal_item = (zone->random.Roll(50) || no_coin);
|
bool has_coin = ((money[PickPocketPlatinum] | money[PickPocketGold] | money[PickPocketSilver] | money[PickPocketCopper]) != 0);
|
||||||
if (steal_item)
|
bool steal_item = (steal_skill >= steal_chance && (zone->random.Roll(50) || !has_coin));
|
||||||
{
|
|
||||||
ItemList::iterator cur,end;
|
// still needs to have FindFreeSlot vs PutItemInInventory issue worked out
|
||||||
cur = itemlist.begin();
|
while (steal_item) {
|
||||||
end = itemlist.end();
|
std::vector<std::pair<const Item_Struct*, uint16>> loot_selection; // <const Item_Struct*, charges>
|
||||||
for(; cur != end && x < 49; ++cur) {
|
for (auto item_iter : itemlist) {
|
||||||
ServerLootItem_Struct* citem = *cur;
|
if (!item_iter || !item_iter->item_id)
|
||||||
const Item_Struct* item = database.GetItem(citem->item_id);
|
continue;
|
||||||
if (item)
|
|
||||||
{
|
auto item_test = database.GetItem(item_iter->item_id);
|
||||||
inst = database.CreateItem(item, citem->charges);
|
if (item_test->Magic || !item_test->NoDrop || item_test->ItemType == ItemClassContainer || thief->CheckLoreConflict(item_test))
|
||||||
bool is_arrow = (item->ItemType == ItemTypeArrow) ? true : false;
|
continue;
|
||||||
int slot_id = thief->GetInv().FindFreeSlot(false, true, inst->GetItem()->Size, is_arrow);
|
|
||||||
if (/*!Equipped(item->ID) &&*/
|
loot_selection.push_back(std::make_pair(item_test, ((item_test->Stackable) ? (1) : (item_iter->charges))));
|
||||||
!item->Magic && item->NoDrop != 0 && !inst->IsType(ItemClassContainer) && slot_id != INVALID_INDEX
|
|
||||||
/*&& steal_skill > item->StealSkill*/ )
|
|
||||||
{
|
|
||||||
slot[x] = slot_id;
|
|
||||||
steal_items[x] = item->ID;
|
|
||||||
if (inst->IsStackable())
|
|
||||||
charges[x] = 1;
|
|
||||||
else
|
|
||||||
charges[x] = citem->charges;
|
|
||||||
x++;
|
|
||||||
}
|
}
|
||||||
}
|
if (loot_selection.empty()) {
|
||||||
}
|
|
||||||
if (x > 0)
|
|
||||||
{
|
|
||||||
int random = zone->random.Int(0, x-1);
|
|
||||||
inst = database.CreateItem(steal_items[random], charges[random]);
|
|
||||||
if (inst)
|
|
||||||
{
|
|
||||||
const Item_Struct* item = inst->GetItem();
|
|
||||||
if (item)
|
|
||||||
{
|
|
||||||
if (/*item->StealSkill || */steal_skill >= stealchance)
|
|
||||||
{
|
|
||||||
thief->PutItemInInventory(slot[random], *inst);
|
|
||||||
thief->SendItemPacket(slot[random], inst, ItemPacketTrade);
|
|
||||||
RemoveItem(item->ID);
|
|
||||||
thief->SendPickPocketResponse(this, 0, PickPocketItem, item);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
steal_item = false;
|
steal_item = false;
|
||||||
}
|
break;
|
||||||
else
|
|
||||||
steal_item = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
steal_item = false;
|
|
||||||
}
|
|
||||||
else if (!no_coin)
|
|
||||||
{
|
|
||||||
steal_item = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
thief->Message(0, "This target's pockets are empty");
|
|
||||||
thief->SendPickPocketResponse(this, 0, PickPocketFailed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!steal_item) //Steal money
|
|
||||||
{
|
|
||||||
uint32 amt = zone->random.Int(1, (steal_skill/25)+1);
|
|
||||||
int steal_type = 0;
|
|
||||||
if (!money[0])
|
|
||||||
{
|
|
||||||
steal_type = 1;
|
|
||||||
if (!money[1])
|
|
||||||
{
|
|
||||||
steal_type = 2;
|
|
||||||
if (!money[2])
|
|
||||||
{
|
|
||||||
steal_type = 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zone->random.Roll(stealchance))
|
int random = zone->random.Int(0, (loot_selection.size() - 1));
|
||||||
{
|
uint16 slot_id = thief->GetInv().FindFreeSlot(false, true, (loot_selection[random].first->Size), (loot_selection[random].first->ItemType == ItemTypeArrow));
|
||||||
switch (steal_type)
|
if (slot_id == INVALID_INDEX) {
|
||||||
{
|
steal_item = false;
|
||||||
case 0:{
|
|
||||||
if (amt > GetPlatinum())
|
|
||||||
amt = GetPlatinum();
|
|
||||||
SetPlatinum(GetPlatinum()-amt);
|
|
||||||
thief->AddMoneyToPP(0,0,0,amt,false);
|
|
||||||
thief->SendPickPocketResponse(this, amt, PickPocketPlatinum);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1:{
|
|
||||||
if (amt > GetGold())
|
auto item_inst = database.CreateItem(loot_selection[random].first, loot_selection[random].second);
|
||||||
amt = GetGold();
|
if (item_inst == nullptr) {
|
||||||
SetGold(GetGold()-amt);
|
steal_item = false;
|
||||||
thief->AddMoneyToPP(0,0,amt,0,false);
|
|
||||||
thief->SendPickPocketResponse(this, amt, PickPocketGold);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2:{
|
|
||||||
if (amt > GetSilver())
|
// Successful item pickpocket
|
||||||
amt = GetSilver();
|
if (item_inst->IsStackable() && RuleB(Character, UseStackablePickPocketing)) {
|
||||||
SetSilver(GetSilver()-amt);
|
if (!thief->TryStacking(item_inst, ItemPacketTrade, false, false)) {
|
||||||
thief->AddMoneyToPP(0,amt,0,0,false);
|
thief->PutItemInInventory(slot_id, *item_inst);
|
||||||
thief->SendPickPocketResponse(this, amt, PickPocketSilver);
|
thief->SendItemPacket(slot_id, item_inst, ItemPacketTrade);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
thief->PutItemInInventory(slot_id, *item_inst);
|
||||||
|
thief->SendItemPacket(slot_id, item_inst, ItemPacketTrade);
|
||||||
|
}
|
||||||
|
RemoveItem(item_inst->GetID());
|
||||||
|
thief->SendPickPocketResponse(this, 0, PickPocketItem, item_inst->GetItem());
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!steal_item && has_coin) {
|
||||||
|
uint32 coin_amount = zone->random.Int(1, (steal_skill / 25) + 1);
|
||||||
|
|
||||||
|
int coin_type = PickPocketPlatinum;
|
||||||
|
while (coin_type <= PickPocketCopper) {
|
||||||
|
if (money[coin_type]) {
|
||||||
|
if (coin_amount > money[coin_type])
|
||||||
|
coin_amount = money[coin_type];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 3:{
|
++coin_type;
|
||||||
if (amt > GetCopper())
|
}
|
||||||
amt = GetCopper();
|
if (coin_type > PickPocketCopper)
|
||||||
SetCopper(GetCopper()-amt);
|
|
||||||
thief->AddMoneyToPP(amt,0,0,0,false);
|
|
||||||
thief->SendPickPocketResponse(this, amt, PickPocketCopper);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
memset(money, 0, (sizeof(int) * 6));
|
||||||
}
|
money[coin_type] = coin_amount;
|
||||||
else
|
|
||||||
{
|
if (zone->random.Roll(steal_chance)) { // Successful coin pickpocket
|
||||||
|
switch (coin_type) {
|
||||||
|
case PickPocketPlatinum:
|
||||||
|
SetPlatinum(GetPlatinum() - coin_amount);
|
||||||
|
break;
|
||||||
|
case PickPocketGold:
|
||||||
|
SetGold(GetGold() - coin_amount);
|
||||||
|
break;
|
||||||
|
case PickPocketSilver:
|
||||||
|
SetSilver(GetSilver() - coin_amount);
|
||||||
|
break;
|
||||||
|
case PickPocketCopper:
|
||||||
|
SetCopper(GetCopper() - coin_amount);
|
||||||
|
break;
|
||||||
|
default: // has_coin..but, doesn't have coin?
|
||||||
thief->SendPickPocketResponse(this, 0, PickPocketFailed);
|
thief->SendPickPocketResponse(this, 0, PickPocketFailed);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
thief->AddMoneyToPP(money[3], money[2], money[1], money[0], false);
|
||||||
|
thief->SendPickPocketResponse(this, coin_amount, coin_type);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
safe_delete(inst);
|
|
||||||
|
thief->SendPickPocketResponse(this, 0, PickPocketFailed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
thief->Message(0, "This target's pockets are empty");
|
||||||
|
thief->SendPickPocketResponse(this, 0, PickPocketFailed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mob::NPCSpecialAttacks(const char* parse, int permtag, bool reset, bool remove) {
|
void Mob::NPCSpecialAttacks(const char* parse, int permtag, bool reset, bool remove) {
|
||||||
|
|||||||
@ -165,7 +165,7 @@ public:
|
|||||||
virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther);
|
virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther);
|
||||||
|
|
||||||
void GoToBind(uint8 bindnum = 0) { GMMove(m_SpawnPoint.x, m_SpawnPoint.y, m_SpawnPoint.z, m_SpawnPoint.w); }
|
void GoToBind(uint8 bindnum = 0) { GMMove(m_SpawnPoint.x, m_SpawnPoint.y, m_SpawnPoint.z, m_SpawnPoint.w); }
|
||||||
void Gate();
|
void Gate(uint8 bindnum = 0);
|
||||||
|
|
||||||
void GetPetState(SpellBuff_Struct *buffs, uint32 *items, char *name);
|
void GetPetState(SpellBuff_Struct *buffs, uint32 *items, char *name);
|
||||||
void SetPetState(SpellBuff_Struct *buffs, uint32 *items);
|
void SetPetState(SpellBuff_Struct *buffs, uint32 *items);
|
||||||
|
|||||||
@ -1072,7 +1072,7 @@ XS(XS_Client_SetBindPoint)
|
|||||||
new_z = (float)SvNV(ST(5));
|
new_z = (float)SvNV(ST(5));
|
||||||
}
|
}
|
||||||
|
|
||||||
THIS->SetBindPoint(to_zone, to_instance, glm::vec3(new_x, new_y, new_z));
|
THIS->SetBindPoint(0, to_zone, to_instance, glm::vec3(new_x, new_y, new_z));
|
||||||
}
|
}
|
||||||
XSRETURN_EMPTY;
|
XSRETURN_EMPTY;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -283,7 +283,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
|
|||||||
npc_type->level += 1 + ((int)act_power / 25) > npc_type->level + RuleR(Pets, PetPowerLevelCap) ? RuleR(Pets, PetPowerLevelCap) : 1 + ((int)act_power / 25); // gains an additional level for every 25 pet power
|
npc_type->level += 1 + ((int)act_power / 25) > npc_type->level + RuleR(Pets, PetPowerLevelCap) ? RuleR(Pets, PetPowerLevelCap) : 1 + ((int)act_power / 25); // gains an additional level for every 25 pet power
|
||||||
npc_type->min_dmg = (npc_type->min_dmg * (1 + (scale_power / 2)));
|
npc_type->min_dmg = (npc_type->min_dmg * (1 + (scale_power / 2)));
|
||||||
npc_type->max_dmg = (npc_type->max_dmg * (1 + (scale_power / 2)));
|
npc_type->max_dmg = (npc_type->max_dmg * (1 + (scale_power / 2)));
|
||||||
npc_type->size = npc_type->size * (1 + (scale_power / 2)) > npc_type->size * 3 ? npc_type->size * 3 : (1 + (scale_power / 2));
|
npc_type->size = npc_type->size * (1 + (scale_power / 2)) > npc_type->size * 3 ? npc_type->size * 3 : npc_type-> size * (1 + (scale_power / 2));
|
||||||
}
|
}
|
||||||
record.petpower = act_power;
|
record.petpower = act_power;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1565,7 +1565,7 @@ void QuestManager::ding() {
|
|||||||
void QuestManager::rebind(int zoneid, const glm::vec3& location) {
|
void QuestManager::rebind(int zoneid, const glm::vec3& location) {
|
||||||
QuestManagerCurrentQuestVars();
|
QuestManagerCurrentQuestVars();
|
||||||
if(initiator && initiator->IsClient()) {
|
if(initiator && initiator->IsClient()) {
|
||||||
initiator->SetBindPoint(zoneid, 0, location);
|
initiator->SetBindPoint(0, zoneid, 0, location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -904,7 +904,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
|
|||||||
WDmg = weapon_damage;
|
WDmg = weapon_damage;
|
||||||
|
|
||||||
if (LaunchProjectile){//1: Shoot the Projectile once we calculate weapon damage.
|
if (LaunchProjectile){//1: Shoot the Projectile once we calculate weapon damage.
|
||||||
TryProjectileAttack(other, AmmoItem, SkillArchery, WDmg, RangeWeapon, Ammo, AmmoSlot, speed);
|
TryProjectileAttack(other, AmmoItem, SkillArchery, (WDmg + ADmg), RangeWeapon, Ammo, AmmoSlot, speed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -926,6 +926,9 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
|
|||||||
|
|
||||||
MaxDmg += MaxDmg*bonusArcheryDamageModifier / 100;
|
MaxDmg += MaxDmg*bonusArcheryDamageModifier / 100;
|
||||||
|
|
||||||
|
if (RuleB(Combat, ProjectileDmgOnImpact))
|
||||||
|
Log.Out(Logs::Detail, Logs::Combat, "Bow and Arrow DMG %d, Max Damage %d.", WDmg, MaxDmg);
|
||||||
|
else
|
||||||
Log.Out(Logs::Detail, Logs::Combat, "Bow DMG %d, Arrow DMG %d, Max Damage %d.", WDmg, ADmg, MaxDmg);
|
Log.Out(Logs::Detail, Logs::Combat, "Bow DMG %d, Arrow DMG %d, Max Damage %d.", WDmg, ADmg, MaxDmg);
|
||||||
|
|
||||||
bool dobonus = false;
|
bool dobonus = false;
|
||||||
|
|||||||
@ -499,7 +499,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SE_GateCastersBindpoint: //Shin: Used on Teleport Bind.
|
case SE_GateCastersBindpoint: // Used on Teleport Bind.
|
||||||
case SE_Teleport: // gates, rings, circles, etc
|
case SE_Teleport: // gates, rings, circles, etc
|
||||||
case SE_Teleport2:
|
case SE_Teleport2:
|
||||||
{
|
{
|
||||||
@ -532,13 +532,16 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (effect == SE_GateCastersBindpoint && caster->IsClient())
|
if (effect == SE_GateCastersBindpoint && caster->IsClient())
|
||||||
{ //Shin: Teleport Bind uses caster's bind point
|
{ // Teleport Bind uses caster's bind point
|
||||||
x = caster->CastToClient()->GetBindX();
|
int index = spells[spell_id].base[i] - 1;
|
||||||
y = caster->CastToClient()->GetBindY();
|
if (index < 0 || index > 4)
|
||||||
z = caster->CastToClient()->GetBindZ();
|
index = 0;
|
||||||
heading = caster->CastToClient()->GetBindHeading();
|
x = caster->CastToClient()->GetBindX(index);
|
||||||
|
y = caster->CastToClient()->GetBindY(index);
|
||||||
|
z = caster->CastToClient()->GetBindZ(index);
|
||||||
|
heading = caster->CastToClient()->GetBindHeading(index);
|
||||||
//target_zone = caster->CastToClient()->GetBindZoneId(); target_zone doesn't work due to const char
|
//target_zone = caster->CastToClient()->GetBindZoneId(); target_zone doesn't work due to const char
|
||||||
CastToClient()->MovePC(caster->CastToClient()->GetBindZoneID(), 0, x, y, z, heading);
|
CastToClient()->MovePC(caster->CastToClient()->GetBindZoneID(index), 0, x, y, z, heading);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -917,7 +920,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
|||||||
if(caster->IsClient() && caster != this)
|
if(caster->IsClient() && caster != this)
|
||||||
caster->CastToClient()->QueuePacket(message_packet);
|
caster->CastToClient()->QueuePacket(message_packet);
|
||||||
|
|
||||||
CastToClient()->SetBindPoint();
|
CastToClient()->SetBindPoint(spells[spell_id].base[i] - 1);
|
||||||
Save();
|
Save();
|
||||||
safe_delete(action_packet);
|
safe_delete(action_packet);
|
||||||
safe_delete(message_packet);
|
safe_delete(message_packet);
|
||||||
@ -966,7 +969,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
|||||||
if(caster->IsClient() && caster != this)
|
if(caster->IsClient() && caster != this)
|
||||||
caster->CastToClient()->QueuePacket(message_packet);
|
caster->CastToClient()->QueuePacket(message_packet);
|
||||||
|
|
||||||
CastToClient()->SetBindPoint();
|
CastToClient()->SetBindPoint(spells[spell_id].base[i] - 1);
|
||||||
Save();
|
Save();
|
||||||
safe_delete(action_packet);
|
safe_delete(action_packet);
|
||||||
safe_delete(message_packet);
|
safe_delete(message_packet);
|
||||||
@ -1002,7 +1005,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
|||||||
if(caster->IsClient() && caster != this)
|
if(caster->IsClient() && caster != this)
|
||||||
caster->CastToClient()->QueuePacket(message_packet);
|
caster->CastToClient()->QueuePacket(message_packet);
|
||||||
|
|
||||||
CastToClient()->SetBindPoint();
|
CastToClient()->SetBindPoint(spells[spell_id].base[i] - 1);
|
||||||
Save();
|
Save();
|
||||||
safe_delete(action_packet);
|
safe_delete(action_packet);
|
||||||
safe_delete(message_packet);
|
safe_delete(message_packet);
|
||||||
@ -1012,7 +1015,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SE_Gate: //TO DO: Add support for secondary and tertiary gate abilities (base2)
|
case SE_Gate:
|
||||||
{
|
{
|
||||||
#ifdef SPELL_EFFECT_SPAM
|
#ifdef SPELL_EFFECT_SPAM
|
||||||
snprintf(effect_desc, _EDLEN, "Gate");
|
snprintf(effect_desc, _EDLEN, "Gate");
|
||||||
@ -1020,7 +1023,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
|||||||
if(!spellbonuses.AntiGate){
|
if(!spellbonuses.AntiGate){
|
||||||
|
|
||||||
if(zone->random.Roll(effect_value))
|
if(zone->random.Roll(effect_value))
|
||||||
Gate();
|
Gate(spells[spell_id].base2[i] - 1);
|
||||||
else
|
else
|
||||||
caster->Message_StringID(MT_SpellFailure,GATE_FAIL);
|
caster->Message_StringID(MT_SpellFailure,GATE_FAIL);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1260,30 +1260,27 @@ bool ZoneDatabase::LoadCharacterPotions(uint32 character_id, PlayerProfile_Struc
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ZoneDatabase::LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp){
|
bool ZoneDatabase::LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct *pp)
|
||||||
std::string query = StringFormat("SELECT `zone_id`, `instance_id`, `x`, `y`, `z`, `heading`, `is_home` FROM `character_bind` WHERE `id` = %u LIMIT 2", character_id);
|
{
|
||||||
|
std::string query = StringFormat("SELECT `slot`, `zone_id`, `instance_id`, `x`, `y`, `z`, `heading` FROM "
|
||||||
|
"`character_bind` WHERE `id` = %u LIMIT 5",
|
||||||
|
character_id);
|
||||||
auto results = database.QueryDatabase(query);
|
auto results = database.QueryDatabase(query);
|
||||||
|
|
||||||
|
if (!results.RowCount()) // SHIT -- this actually isn't good
|
||||||
|
return true;
|
||||||
|
|
||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
|
int index = atoi(row[0]);
|
||||||
/* Is home bind */
|
if (index < 0 || index > 4)
|
||||||
if (atoi(row[6]) == 1){
|
|
||||||
pp->binds[4].zoneId = atoi(row[0]);
|
|
||||||
pp->binds[4].instance_id = atoi(row[1]);
|
|
||||||
pp->binds[4].x = atoi(row[2]);
|
|
||||||
pp->binds[4].y = atoi(row[3]);
|
|
||||||
pp->binds[4].z = atoi(row[4]);
|
|
||||||
pp->binds[4].heading = atoi(row[5]);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
/* Is regular bind point */
|
pp->binds[index].zoneId = atoi(row[1]);
|
||||||
pp->binds[0].zoneId = atoi(row[0]);
|
pp->binds[index].instance_id = atoi(row[2]);
|
||||||
pp->binds[0].instance_id = atoi(row[1]);
|
pp->binds[index].x = atoi(row[3]);
|
||||||
pp->binds[0].x = atoi(row[2]);
|
pp->binds[index].y = atoi(row[4]);
|
||||||
pp->binds[0].y = atoi(row[3]);
|
pp->binds[index].z = atoi(row[5]);
|
||||||
pp->binds[0].z = atoi(row[4]);
|
pp->binds[index].heading = atoi(row[6]);
|
||||||
pp->binds[0].heading = atoi(row[5]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -1295,19 +1292,23 @@ bool ZoneDatabase::SaveCharacterLanguage(uint32 character_id, uint32 lang_id, ui
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ZoneDatabase::SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, const glm::vec4& position, uint8 is_home){
|
bool ZoneDatabase::SaveCharacterBindPoint(uint32 character_id, const BindStruct &bind, uint32 bind_num)
|
||||||
if (zone_id <= 0) {
|
{
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Save Home Bind Point */
|
/* Save Home Bind Point */
|
||||||
std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)"
|
std::string query =
|
||||||
" VALUES (%u, %u, %u, %f, %f, %f, %f, %i)", character_id, zone_id, instance_id, position.x, position.y, position.z, position.w, is_home);
|
StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot) VALUES (%u, "
|
||||||
Log.Out(Logs::General, Logs::None, "ZoneDatabase::SaveCharacterBindPoint for character ID: %i zone_id: %u instance_id: %u position: %s ishome: %u", character_id, zone_id, instance_id, to_string(position).c_str(), is_home);
|
"%u, %u, %f, %f, %f, %f, %i)",
|
||||||
|
character_id, bind.zoneId, bind.instance_id, bind.x, bind.y, bind.z, bind.heading, bind_num);
|
||||||
|
|
||||||
|
Log.Out(Logs::General, Logs::None, "ZoneDatabase::SaveCharacterBindPoint for character ID: %i zone_id: %u "
|
||||||
|
"instance_id: %u position: %f %f %f %f bind_num: %u",
|
||||||
|
character_id, bind.zoneId, bind.instance_id, bind.x, bind.y, bind.z, bind.heading, bind_num);
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if (!results.RowsAffected()) {
|
if (!results.RowsAffected())
|
||||||
Log.Out(Logs::General, Logs::None, "ERROR Bind Home Save: %s. %s", results.ErrorMessage().c_str(), query.c_str());
|
Log.Out(Logs::General, Logs::None, "ERROR Bind Home Save: %s. %s", results.ErrorMessage().c_str(),
|
||||||
}
|
query.c_str());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -277,7 +277,7 @@ public:
|
|||||||
bool LoadCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp);
|
bool LoadCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp);
|
||||||
|
|
||||||
/* Character Data Saves */
|
/* Character Data Saves */
|
||||||
bool SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, const glm::vec4& position, uint8 is_home);
|
bool SaveCharacterBindPoint(uint32 character_id, const BindStruct &bind, uint32 bind_num);
|
||||||
bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp);
|
bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp);
|
||||||
bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp);
|
bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp);
|
||||||
bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level, uint32 charges);
|
bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level, uint32 charges);
|
||||||
|
|||||||
@ -707,37 +707,40 @@ void Client::GoToSafeCoords(uint16 zone_id, uint16 instance_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Mob::Gate() {
|
void Mob::Gate(uint8 bindnum) {
|
||||||
GoToBind();
|
GoToBind(bindnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::Gate() {
|
void Client::Gate(uint8 bindnum) {
|
||||||
Mob::Gate();
|
Mob::Gate(bindnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NPC::Gate() {
|
void NPC::Gate(uint8 bindnum) {
|
||||||
entity_list.MessageClose_StringID(this, true, 200, MT_Spells, GATES, GetCleanName());
|
entity_list.MessageClose_StringID(this, true, 200, MT_Spells, GATES, GetCleanName());
|
||||||
|
|
||||||
Mob::Gate();
|
Mob::Gate(bindnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::SetBindPoint(int to_zone, int to_instance, const glm::vec3& location) {
|
void Client::SetBindPoint(int bind_num, int to_zone, int to_instance, const glm::vec3 &location)
|
||||||
|
{
|
||||||
|
if (bind_num < 0 || bind_num >= 4)
|
||||||
|
bind_num = 0;
|
||||||
|
|
||||||
if (to_zone == -1) {
|
if (to_zone == -1) {
|
||||||
m_pp.binds[0].zoneId = zone->GetZoneID();
|
m_pp.binds[bind_num].zoneId = zone->GetZoneID();
|
||||||
m_pp.binds[0].instance_id = (zone->GetInstanceID() != 0 && zone->IsInstancePersistent()) ? zone->GetInstanceID() : 0;
|
m_pp.binds[bind_num].instance_id =
|
||||||
m_pp.binds[0].x = m_Position.x;
|
(zone->GetInstanceID() != 0 && zone->IsInstancePersistent()) ? zone->GetInstanceID() : 0;
|
||||||
m_pp.binds[0].y = m_Position.y;
|
m_pp.binds[bind_num].x = m_Position.x;
|
||||||
m_pp.binds[0].z = m_Position.z;
|
m_pp.binds[bind_num].y = m_Position.y;
|
||||||
|
m_pp.binds[bind_num].z = m_Position.z;
|
||||||
|
} else {
|
||||||
|
m_pp.binds[bind_num].zoneId = to_zone;
|
||||||
|
m_pp.binds[bind_num].instance_id = to_instance;
|
||||||
|
m_pp.binds[bind_num].x = location.x;
|
||||||
|
m_pp.binds[bind_num].y = location.y;
|
||||||
|
m_pp.binds[bind_num].z = location.z;
|
||||||
}
|
}
|
||||||
else {
|
database.SaveCharacterBindPoint(this->CharacterID(), m_pp.binds[bind_num], bind_num);
|
||||||
m_pp.binds[0].zoneId = to_zone;
|
|
||||||
m_pp.binds[0].instance_id = to_instance;
|
|
||||||
m_pp.binds[0].x = location.x;
|
|
||||||
m_pp.binds[0].y = location.y;
|
|
||||||
m_pp.binds[0].z = location.z;
|
|
||||||
}
|
|
||||||
auto regularBindPoint = glm::vec4(m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, 0.0f);
|
|
||||||
database.SaveCharacterBindPoint(this->CharacterID(), m_pp.binds[0].zoneId, m_pp.binds[0].instance_id, regularBindPoint, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::GoToBind(uint8 bindnum) {
|
void Client::GoToBind(uint8 bindnum) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user