/* * psitemstats.cpp * * Copyright (C) 2001 Atomic Blue (info@planeshift.it, http://www.atomicblue.org) * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation (version 2 of the License) * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include #include #include "imesh/object.h" #include #include "iengine/mesh.h" #include #include #include #include "psglyph.h" #include "psitem.h" #include "psitemstats.h" #include "util/log.h" #include "util/psstring.h" #include "util/serverconsole.h" #include "../globals.h" #include "../psserver.h" #include "../cachemanager.h" #include "psmerchantinfo.h" //----------------------------------------------------------------------------- psItemArmorStats::psItemArmorStats() { armor_type = PSITEMSTATS_ARMORTYPE_NONE; armor_class = 0; memset(damage_protection,0,sizeof(damage_protection)); hardness = 0.0; } float psItemArmorStats::Protection(PSITEMSTATS_DAMAGETYPE dmgtype) { if (dmgtype <0 || dmgtype >= PSITEMSTATS_DAMAGETYPE_COUNT) return 0.0f; return damage_protection[dmgtype]; } void psItemArmorStats::ReadStats( iResultRow& row ) { hardness = row.GetFloat("armor_hardness"); damage_protection[PSITEMSTATS_DAMAGETYPE_SLASH] = row.GetFloat("armor_prot_slash"); damage_protection[PSITEMSTATS_DAMAGETYPE_BLUNT] = row.GetFloat("armor_prot_blunt"); damage_protection[PSITEMSTATS_DAMAGETYPE_PIERCE] = row.GetFloat("armor_prot_pierce"); damage_protection[PSITEMSTATS_DAMAGETYPE_FORCE] = row.GetFloat("armor_prot_force"); damage_protection[PSITEMSTATS_DAMAGETYPE_FIRE] = row.GetFloat("armor_prot_fire"); damage_protection[PSITEMSTATS_DAMAGETYPE_ICE] = row.GetFloat("armor_prot_ice"); damage_protection[PSITEMSTATS_DAMAGETYPE_AIR] = row.GetFloat("armor_prot_air"); damage_protection[PSITEMSTATS_DAMAGETYPE_POISON] = row.GetFloat("armor_prot_poison"); damage_protection[PSITEMSTATS_DAMAGETYPE_DISEASE] = row.GetFloat("armor_prot_disease"); damage_protection[PSITEMSTATS_DAMAGETYPE_HOLY] = row.GetFloat("armor_prot_holy"); damage_protection[PSITEMSTATS_DAMAGETYPE_UNHOLY] = row.GetFloat("armor_prot_unholy"); csString temp(row["armorvsweapon_type"]); if ( temp.Length() == 2 ) { if (temp.GetAt(0) == '1') armor_type = PSITEMSTATS_ARMORTYPE_LIGHT; else if (temp.GetAt(0) == '2') armor_type = PSITEMSTATS_ARMORTYPE_MEDIUM; else if (temp.GetAt(0) == '3') armor_type = PSITEMSTATS_ARMORTYPE_HEAVY; armor_class = temp.GetAt(1); } } //----------------------------------------------------------------------------- psItemWeaponStats::psItemWeaponStats() { weapon_type=PSITEMSTATS_WEAPONTYPE_NONE; memset(weapon_skill,0,sizeof(weapon_skill)); memset(attribute_bonuses,0,sizeof(attribute_bonuses)); memset(damages,0,sizeof(damages)); memset(damage_percents,0,sizeof(damage_percents)); latency=0.0f; penetration=0.0f; untargeted_block_value=0.0f; targeted_block_value=0.0f; counter_block_value=0.0f; } void psItemWeaponStats::ReadStats( iResultRow& row ) { csString type( row["item_type"] ); if ( type == "SWORD" ) weapon_type = PSITEMSTATS_WEAPONTYPE_SWORD; else if ( type == "AXE" ) weapon_type = PSITEMSTATS_WEAPONTYPE_AXE; else if ( type == "DAGGER" ) weapon_type = PSITEMSTATS_WEAPONTYPE_DAGGER; else if ( type == "HAMMER" ) weapon_type = PSITEMSTATS_WEAPONTYPE_HAMMER; else if ( type == "BOW" ) weapon_type = PSITEMSTATS_WEAPONTYPE_BOW; else if ( type == "CROSSBOW" ) weapon_type = PSITEMSTATS_WEAPONTYPE_CROSSBOW; else if ( type == "SLING" ) weapon_type = PSITEMSTATS_WEAPONTYPE_SLING; weapon_skill[PSITEMSTATS_WEAPONSKILL_INDEX_0] = CacheManager::GetSingleton().ConvertSkill(row.GetInt("item_skill_id_1")); weapon_skill[PSITEMSTATS_WEAPONSKILL_INDEX_1] = CacheManager::GetSingleton().ConvertSkill(row.GetInt("item_skill_id_2")); weapon_skill[PSITEMSTATS_WEAPONSKILL_INDEX_2] = CacheManager::GetSingleton().ConvertSkill(row.GetInt("item_skill_id_3")); latency = row.GetFloat("weapon_speed"); damages[PSITEMSTATS_DAMAGETYPE_SLASH] = row.GetFloat("weapon_dmg_slash"); damages[PSITEMSTATS_DAMAGETYPE_BLUNT] = row.GetFloat("weapon_dmg_blunt"); damages[PSITEMSTATS_DAMAGETYPE_PIERCE] = row.GetFloat("weapon_dmg_pierce"); damages[PSITEMSTATS_DAMAGETYPE_FORCE] = row.GetFloat("weapon_dmg_force"); damages[PSITEMSTATS_DAMAGETYPE_FIRE] = row.GetFloat("weapon_dmg_fire"); damages[PSITEMSTATS_DAMAGETYPE_ICE] = row.GetFloat("weapon_dmg_ice"); damages[PSITEMSTATS_DAMAGETYPE_AIR] = row.GetFloat("weapon_dmg_air"); damages[PSITEMSTATS_DAMAGETYPE_POISON] = row.GetFloat("weapon_dmg_poison"); damages[PSITEMSTATS_DAMAGETYPE_DISEASE] = row.GetFloat("weapon_dmg_disease"); damages[PSITEMSTATS_DAMAGETYPE_HOLY] = row.GetFloat("weapon_dmg_holy"); damages[PSITEMSTATS_DAMAGETYPE_UNHOLY] = row.GetFloat("weapon_dmg_unholy"); damage_percents[PSITEMSTATS_DAMAGETYPE_SLASH] = row.GetFloat("weapon_dmg_pct_slash"); damage_percents[PSITEMSTATS_DAMAGETYPE_BLUNT] = row.GetFloat("weapon_dmg_pct_blunt"); damage_percents[PSITEMSTATS_DAMAGETYPE_PIERCE] = row.GetFloat("weapon_dmg_pct_pierce"); damage_percents[PSITEMSTATS_DAMAGETYPE_FORCE] = row.GetFloat("weapon_dmg_pct_force"); damage_percents[PSITEMSTATS_DAMAGETYPE_FIRE] = row.GetFloat("weapon_dmg_pct_fire"); damage_percents[PSITEMSTATS_DAMAGETYPE_ICE] = row.GetFloat("weapon_dmg_pct_ice"); damage_percents[PSITEMSTATS_DAMAGETYPE_AIR] = row.GetFloat("weapon_dmg_pct_air"); damage_percents[PSITEMSTATS_DAMAGETYPE_POISON] = row.GetFloat("weapon_dmg_pct_poison"); damage_percents[PSITEMSTATS_DAMAGETYPE_DISEASE] = row.GetFloat("weapon_dmg_pct_disease"); damage_percents[PSITEMSTATS_DAMAGETYPE_HOLY] = row.GetFloat("weapon_dmg_pct_holy"); damage_percents[PSITEMSTATS_DAMAGETYPE_UNHOLY] = row.GetFloat("weapon_dmg_pct_unholy"); penetration = row.GetFloat("weapon_penetration"); targeted_block_value = row.GetFloat("weapon_block_targeted"); untargeted_block_value = row.GetFloat("weapon_block_untargeted"); counter_block_value = row.GetFloat("weapon_counterblock"); } PSSKILL psItemWeaponStats::Skill(PSITEMSTATS_WEAPONSKILL_INDEX index) { if (index < 0 || index >= PSITEMSTATS_WEAPONSKILL_INDEX_COUNT) return PSSKILL_NONE; return weapon_skill[index]; } PSITEMSTATS_STAT psItemWeaponStats::AttributeBonusType(PSITEMSTATS_STAT_BONUS_INDEX index) { if (index<0 || index >= PSITEMSTATS_STAT_BONUS_INDEX_COUNT) return PSITEMSTATS_STAT_NONE; return attribute_bonuses[index].attribute_id; } float psItemWeaponStats::AttributeBonusMax(PSITEMSTATS_STAT_BONUS_INDEX index) { if (index<0 || index >= PSITEMSTATS_STAT_BONUS_INDEX_COUNT) return 0.0f; return attribute_bonuses[index].bonus_max; } float psItemWeaponStats::Damage(PSITEMSTATS_DAMAGETYPE dmgtype) { if (dmgtype<0 || dmgtype >= PSITEMSTATS_DAMAGETYPE_COUNT) return 0.0f; return damages[dmgtype]; } float psItemWeaponStats::ExtraDamagePercent(PSITEMSTATS_DAMAGETYPE dmgtype) { if (dmgtype < 0 || dmgtype >= PSITEMSTATS_DAMAGETYPE_COUNT) return 0.0f; return damage_percents[dmgtype]; } //----------------------------------------------------------------------------- psItemAmmoStats::psItemAmmoStats() { ammunition_type = PSITEMSTATS_AMMOTYPE_NONE; } psItemAmmoStats::~psItemAmmoStats() { } void psItemAmmoStats::ReadStats( iResultRow& row ) { csString type( row["item_type"] ); if ( type == "ARROW" ) ammunition_type = PSITEMSTATS_AMMOTYPE_ARROWS; else if ( type == "BOLT" ) ammunition_type = PSITEMSTATS_AMMOTYPE_BOLTS; else if ( type == "ROCK" ) ammunition_type = PSITEMSTATS_AMMOTYPE_ROCKS; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Definition of the itempool for psItemStats PoolAllocator psItemStats::itempool; void *psItemStats::operator new(size_t allocSize) { CS_ASSERT(allocSize<=sizeof(psItemStats)); return (void *)itempool.CallFromNew(); } void psItemStats::operator delete(void *releasePtr) { itempool.CallFromDelete((psItemStats *)releasePtr); } psItemStats::psItemStats() { uid=0; name = ""; description=""; weight=0.0f; size=0; container_max_size=0; valid_slots=0x00000000; decay_rate=0; flags=0x00000000; mesh_name=NULL; texture_name.Clear(); texturepart_name.Clear(); image_name=NULL; visible_distance = DEF_PROX_DIST; } psItemStats::~psItemStats() { } bool psItemStats::ReadItemStats(iResultRow& row) { uid = row.GetUInt32("id"); name = row["name"]; SetDescription(row["description"]); SetProgressionEventEquip( row["prg_evt_equip"] ); SetProgressionEventUnEquip( row["prg_evt_unequip"] ); item_quality = row.GetFloat("item_max_quality"); weight = row.GetFloat("weight"); size = (unsigned short)row.GetInt("size"); container_max_size = (unsigned short)row.GetInt("container_max_size"); visible_distance = row.GetFloat("visible_distance"); decay_rate = row.GetFloat("decay_rate"); // Load in the valid slots for the item. LoadSlots( row ); ParseFlags( row ); if (flags==0) // no type specified is illegal { Error2("Item %s has no valid flags specified.",row["id"] ); return false; } SetArmorVsWeaponType(row["armorvsweapon_type"]); weaponStats.ReadStats( row ); armorStats.ReadStats( row ); ammoStats.ReadStats( row ); // Mesh, Texture, Part and Image strings const char *meshname = CacheManager::GetSingleton().FindCommonString(row.GetUInt32("cstr_id_gfx_mesh")); if (row.GetUInt32("cstr_id_gfx_mesh")!=0 && !meshname) { Error3("Error, no commonstring exists with number %u while loading item_stats.id %u.\n",row.GetUInt32("cstr_id_gfx_mesh"),uid); return false; } else SetMeshName(meshname); const char *texturename = CacheManager::GetSingleton().FindCommonString(row.GetUInt32("cstr_id_gfx_texture")); if (row.GetUInt32("cstr_id_gfx_texture")!=0 && !texturename) { Error3("Error, no commonstring exists with number %u while loading item_stats.id %u.\n",row.GetUInt32("cstr_id_gfx_texture"),uid); return false; } else SetTextureName(texturename); SetPartName(CacheManager::GetSingleton().FindCommonString(row.GetUInt32("cstr_id_part"))); SetImageName(CacheManager::GetSingleton().FindCommonString(row.GetUInt32("cstr_id_gfx_icon"))); SetPartMeshName(CacheManager::GetSingleton().FindCommonString(row.GetUInt32("cstr_id_part_mesh"))); SetPrice(row.GetInt("base_sale_price")); SetCategory(CacheManager::GetSingleton().GetItemCategoryByID(row.GetInt("category_id"))); reqs[0].name = row["requirement_1_name"]; reqs[0].min_value = row.GetFloat("requirement_1_value"); reqs[1].name = row["requirement_2_name"]; reqs[1].min_value = row.GetFloat("requirement_2_value"); reqs[2].name = row["requirement_3_name"]; reqs[2].min_value = row.GetFloat("requirement_3_value"); ammo_item_type_id = row.GetInt("item_type_id_ammo"); spell_id_on_hit = row.GetInt("spell_id_on_hit"); spell_on_hit_probability = row.GetFloat("spell_on_hit_prob"); spell_id_feature = row.GetInt("spell_id_feature"); spell_feature_charges = row.GetInt("spell_feature_charges"); spell_feature_timing = row.GetInt("spell_feature_timing"); SetSound(row["sound"]); int anim_list_id = row.GetInt("item_anim_id"); if (anim_list_id) { anim_list = CacheManager::GetSingleton().FindAnimationList(anim_list_id); if (!anim_list) return false; } else anim_list = NULL; if (row["illum_definition"]) { SetIllumination(row["illum_definition"]); } return true; } void psItemStats::ParseFlags( iResultRow& row ) { psString flagstr(row["flags"]); int z = 0; // Iterates over all the flags in the list and adds that flag to the value if it // has been found in the flag string from the database. while ( CacheManager::GetSingleton().ItemStatFlagArray[z].string != "END" ) { if (flagstr.FindSubString(CacheManager::GetSingleton().ItemStatFlagArray[z].string,0,true)!=-1) { flags |= CacheManager::GetSingleton().ItemStatFlagArray[z].flag; } z++; } } void psItemStats::LoadSlots( iResultRow& row ) { // Valid slots psString slots(row["valid_slots"]); if (slots.FindSubString("BULK",0,true)!=-1) { valid_slots|=PSITEMSTATS_SLOT_BULK; } if (slots.FindSubString("RIGHTHAND",0,true)!=-1) { valid_slots_array.Push(PSCHARACTER_SLOT_RIGHTHAND); valid_slots|=PSITEMSTATS_SLOT_RIGHTHAND; } if (slots.FindSubString("LEFTHAND",0,true)!=-1) { valid_slots_array.Push(PSCHARACTER_SLOT_LEFTHAND); valid_slots|=PSITEMSTATS_SLOT_LEFTHAND; } if (slots.FindSubString("BOTHHANDS",0,true)!=-1) { valid_slots|=PSITEMSTATS_SLOT_BOTHHANDS; valid_slots_array.Push(PSCHARACTER_SLOT_BOTHHANDS); } if (slots.FindSubString("HEAD",0,true)!=-1) { valid_slots_array.Push(PSCHARACTER_SLOT_HEAD); valid_slots|=PSITEMSTATS_SLOT_HEAD; } if (slots.FindSubString("LEFTFINGER",0,true)!=-1) { valid_slots_array.Push(PSCHARACTER_SLOT_LEFTFINGER); valid_slots|=PSITEMSTATS_SLOT_LEFTFINGER; } if (slots.FindSubString("RIGHTFINGER",0,true)!=-1) { valid_slots_array.Push(PSCHARACTER_SLOT_RIGHTFINGER); valid_slots|=PSITEMSTATS_SLOT_RIGHTFINGER; } if (slots.FindSubString("NECK",0,true)!=-1) { valid_slots_array.Push(PSCHARACTER_SLOT_NECK); valid_slots|=PSITEMSTATS_SLOT_NECK; } if (slots.FindSubString("BACK",0,true)!=-1) { valid_slots_array.Push(PSCHARACTER_SLOT_BACK); valid_slots|=PSITEMSTATS_SLOT_BACK; } if (slots.FindSubString("ARMS",0,true)!=-1) { valid_slots_array.Push(PSCHARACTER_SLOT_ARMS); valid_slots|=PSITEMSTATS_SLOT_ARMS; } if (slots.FindSubString("GLOVES",0,true)!=-1) { valid_slots_array.Push(PSCHARACTER_SLOT_GLOVES); valid_slots|=PSITEMSTATS_SLOT_GLOVES; } if (slots.FindSubString("BOOTS",0,true)!=-1) { valid_slots_array.Push(PSCHARACTER_SLOT_BOOTS); valid_slots|=PSITEMSTATS_SLOT_BOOTS; } if (slots.FindSubString("LEGS",0,true)!=-1) { valid_slots|=PSITEMSTATS_SLOT_LEGS; valid_slots_array.Push(PSCHARACTER_SLOT_LEGS); } if (slots.FindSubString("BELT",0,true)!=-1) { valid_slots|=PSITEMSTATS_SLOT_BELT; valid_slots_array.Push(PSCHARACTER_SLOT_BELT); } if (slots.FindSubString("BRACERS",0,true)!=-1) { valid_slots_array.Push(PSITEMSTATS_SLOT_BRACERS); valid_slots|=PSITEMSTATS_SLOT_BRACERS; } if (slots.FindSubString("TORSO",0,true)!=-1) { valid_slots_array.Push(PSCHARACTER_SLOT_TORSO); valid_slots|=PSITEMSTATS_SLOT_TORSO; } if (slots.FindSubString("MIND",0,true)!=-1) { valid_slots_array.Push(PSCHARACTER_SLOT_MIND); valid_slots|=PSITEMSTATS_SLOT_MIND; } if (slots.FindSubString("BANK",0,true)!=-1) { valid_slots|=PSITEMSTATS_SLOT_BANK; } if (slots.FindSubString("CRYSTAL",0,true)!=-1) { valid_slots|=PSITEMSTATS_SLOT_CRYSTAL; } if (slots.FindSubString("AZURE",0,true)!=-1) { valid_slots|=PSITEMSTATS_SLOT_AZURE; } if (slots.FindSubString("RED",0,true)!=-1) { valid_slots|=PSITEMSTATS_SLOT_RED; } if (slots.FindSubString("DARK",0,true)!=-1) { valid_slots|=PSITEMSTATS_SLOT_DARK; } if (slots.FindSubString("BROWN",0,true)!=-1) { valid_slots|=PSITEMSTATS_SLOT_BROWN; } if (slots.FindSubString("BLUE",0,true)!=-1) { valid_slots|=PSITEMSTATS_SLOT_BLUE; } } // Saves current Item Stat values back to the DB. bool psItemStats::Save() { psStringArray fields; bool update_ok=true; // Existing Item, update const char *fieldnames[]= { "name", "weight", "visible_distance", "size", "container_max_size", "decay_rate", //"valid_slots", "flags", "category_id", "base_sale_price", "item_type_id_ammo", "item_anim_id", "description", "weapon_block_targeted", "weapon_block_untargeted", "weapon_counterblock", "weapon_speed", "weapon_dmg_slash", "weapon_dmg_blunt", "weapon_dmg_pierce", "weapon_dmg_force", "weapon_dmg_fire", "weapon_dmg_ice", "weapon_dmg_air", "weapon_dmg_poison", "weapon_dmg_disease", "weapon_dmg_holy", "weapon_dmg_unholy", "armor_prot_slash", "armor_prot_blunt", "armor_prot_pierce", "armor_prot_force", "armor_prot_fire", "armor_prot_ice", "armor_prot_air", "armor_prot_poison", "armor_prot_disease", "armor_prot_holy", "armor_prot_unholy", "cstr_id_gfx_mesh", "requirement_1_name", "requirement_1_value", "requirement_2_name", "requirement_2_value", "requirement_3_name", "requirement_3_value", "prg_evt_equip", "prg_evt_unequip" }; // Owning character ID // INT fields.FormatPush("%u", // FLOAT fields.FormatPush("%1.2f", // STRING fields.Push( fields.Push( this->name ); // name fields.FormatPush( "%1.2f", this->weight ); // weight fields.FormatPush( "%1.2f", this->visible_distance ); // visible_distance fields.FormatPush( "%u", this->size ); // size fields.FormatPush( "%u", this->container_max_size ); // contianer_max_size fields.FormatPush( "%1.2f", this->decay_rate ); // decay_rate //fields.FormatPush( "%u", this->valid_slots ); // valid_slots //fields.FormatPush( "%u", this->flags ); // flags fields.FormatPush( "%u", this->category->id ); // category_id fields.FormatPush( "%u", this->price.GetTotal() ); // base_sales_price fields.FormatPush( "%u", this->ammo_item_type_id ); // item_type_id_ammo fields.FormatPush( "%u", this->anim_list->Get(0)->id ); // item_anim_id fields.Push( this->description ); // description fields.FormatPush ("%1.2f",this->weaponStats.Latency()); // weapon_speed fields.FormatPush ("%1.2f",this->weaponStats.TargetedBlockValue()); //weapon_block_targeted fields.FormatPush ("%1.2f",this->weaponStats.UntargetedBlockValue()); //weapon_block_untargeted fields.FormatPush ("%1.2f",this->weaponStats.CounterBlockValue()); //weapon_counterblock fields.FormatPush("%1.2f", this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_SLASH] ); fields.FormatPush("%1.2f", this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_BLUNT] ); fields.FormatPush("%1.2f", this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_PIERCE] ); fields.FormatPush("%1.2f", this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_FORCE] ); fields.FormatPush("%1.2f", this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_FIRE] ); fields.FormatPush("%1.2f", this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_ICE] ); fields.FormatPush("%1.2f", this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_AIR] ); fields.FormatPush("%1.2f", this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_POISON] ); fields.FormatPush("%1.2f", this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_DISEASE] ); fields.FormatPush("%1.2f", this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_HOLY] ); fields.FormatPush("%1.2f", this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_UNHOLY] ); fields.FormatPush("%1.2f", this->armorStats.damage_protection[PSITEMSTATS_DAMAGETYPE_SLASH] ); fields.FormatPush("%1.2f", this->armorStats.damage_protection[PSITEMSTATS_DAMAGETYPE_BLUNT] ); fields.FormatPush("%1.2f", this->armorStats.damage_protection[PSITEMSTATS_DAMAGETYPE_PIERCE] ); fields.FormatPush("%1.2f", this->armorStats.damage_protection[PSITEMSTATS_DAMAGETYPE_FORCE] ); fields.FormatPush("%1.2f", this->armorStats.damage_protection[PSITEMSTATS_DAMAGETYPE_FIRE] ); fields.FormatPush("%1.2f", this->armorStats.damage_protection[PSITEMSTATS_DAMAGETYPE_ICE] ); fields.FormatPush("%1.2f", this->armorStats.damage_protection[PSITEMSTATS_DAMAGETYPE_AIR] ); fields.FormatPush("%1.2f", this->armorStats.damage_protection[PSITEMSTATS_DAMAGETYPE_POISON] ); fields.FormatPush("%1.2f", this->armorStats.damage_protection[PSITEMSTATS_DAMAGETYPE_DISEASE] ); fields.FormatPush("%1.2f", this->armorStats.damage_protection[PSITEMSTATS_DAMAGETYPE_HOLY] ); fields.FormatPush("%1.2f", this->armorStats.damage_protection[PSITEMSTATS_DAMAGETYPE_UNHOLY] ); fields.FormatPush("%u", CacheManager::GetSingleton().FindCommonStringID( this->mesh_name ) ); //Mesh // stat requirements fields.Push( this->reqs[0].name); fields.FormatPush( "%1.2f", this->reqs[0].min_value); fields.Push( this->reqs[1].name); fields.FormatPush( "%1.2f", this->reqs[1].min_value); fields.Push( this->reqs[2].name); fields.FormatPush( "%1.2f", this->reqs[2].min_value); // equip/unequip events fields.Push( this->progressionEventEquip ); fields.Push( this->progressionEventUnEquip ); // Save this entry update_ok &= db->GenericUpdateWithID("item_stats", "id", GetUIDStr(), fieldnames, fields ); return update_ok; } // If the item is a weapon, use a whole string // If the item is an armor, first char is 1,2,3 and second is a,b,c void psItemStats::SetArmorVsWeaponType(const char* v) { if(!v) return; if (GetIsMeleeWeapon() || GetIsRangeWeapon()) { weapon_type = v; } } void psItemStats::GetArmorVsWeaponType(csString& buff) { if (GetIsMeleeWeapon() || GetIsRangeWeapon()) { buff = weapon_type; return; } else { // Need to do some formating here since the values are splitten csString formated; switch(armorStats.Type()) { case PSITEMSTATS_ARMORTYPE_LIGHT: { formated = "1"; break; } case PSITEMSTATS_ARMORTYPE_MEDIUM: { formated = "2"; break; } case PSITEMSTATS_ARMORTYPE_HEAVY: { formated = "3"; break; } default: break; } formated += armorStats.Class(); buff = formated; return; } //buff = NULL; // @@@ Jorrit: I think the below is the intention rather then the above? // Fixes a warning. buff.Clear (); } int psItemStats::GetAttackAnimID(unsigned int skill_level, iCelEntity *entity) { if (anim_list) { int max; for (max = 0; max < (int)anim_list->Length(); max++) { if (anim_list->Get(max)->min_level_required >(int) skill_level) break; } int which = psserver->rng->Get(max); if (anim_list->Get(which)->anim_id == csInvalidStringID) { anim_list->Get(which)->anim_id = CacheManager::GetSingleton().GetMsgStrings()->Request(anim_list->Get(which)->anim_name); return anim_list->Get(which)->anim_id; } else { Debug2(LOG_COMBAT, uid, "Sending anim %s.\n",anim_list->Get(which)->anim_name.GetData() ); return anim_list->Get(which)->anim_id; } } else return 0; } bool psItemStats::GetIsConsumable() { return (flags & PSITEMSTATS_FLAG_CONSUMABLE) ? true : false; } bool psItemStats::GetIsMeleeWeapon() { return (flags & PSITEMSTATS_FLAG_IS_A_MELEE_WEAPON); } bool psItemStats::GetIsArmor() { return (flags & PSITEMSTATS_FLAG_IS_ARMOR) ? true : false; } bool psItemStats::IsMoney() { return ( (flags & PSITEMSTATS_FLAG_TRIA) || (flags & PSITEMSTATS_FLAG_HEXA) || (flags & PSITEMSTATS_FLAG_OCTA) || (flags & PSITEMSTATS_FLAG_CIRCLE) ); } bool psItemStats::GetIsRangeWeapon() { return (flags & PSITEMSTATS_FLAG_IS_A_RANGED_WEAPON) ? true : false; } bool psItemStats::GetIsAmmo() { return (flags & PSITEMSTATS_FLAG_IS_AMMO) ? true : false; } bool psItemStats::GetIsShield() { return (flags & PSITEMSTATS_FLAG_IS_A_SHIELD)? true : false ; } bool psItemStats::GetIsContainer() { return (flags & PSITEMSTATS_FLAG_IS_A_CONTAINER) ? true : false; } bool psItemStats::GetCanTransform() { return (flags & PSITEMSTATS_FLAG_CAN_TRANSFORM) ? true : false; } bool psItemStats::GetUsesAmmo() { return (flags & PSITEMSTATS_FLAG_USES_AMMO) ? true : false; } bool psItemStats::GetIsStackable() { return (flags & PSITEMSTATS_FLAG_IS_STACKABLE) ? true : false; } bool psItemStats::GetIsReadable() { return (flags & PSITEMSTATS_FLAG_IS_READABLE) ? true : false; } bool psItemStats::GetIsWriteable() { return (flags & PSITEMSTATS_FLAG_IS_WRITEABLE) ? true : false; } bool psItemStats::GetIsGlyph() { return (flags & PSITEMSTATS_FLAG_IS_GLYPH) ? true : false; } uint32 psItemStats::GetUID() { return uid; } const char *psItemStats::GetUIDStr() { static char str[20]; sprintf(str,"%u",uid); return str; } const char *psItemStats::GetName() { return name; } void psItemStats::SetName(const char *v) { if (!v) return; name = v; } const char *psItemStats::GetDescription() { return description; } void psItemStats::SetDescription(const char *v) { if (!v) return; description = v; } float psItemStats::GetWeight() { return weight; } unsigned short psItemStats::GetSize() { return size; } unsigned short psItemStats::GetContainerMaxSize() { return container_max_size; } float psItemStats::GetVisibleDistance() { return visible_distance; } PSITEMSTATS_SLOTLIST psItemStats::GetValidSlots() { return valid_slots; } bool psItemStats::FitsInSlots(PSITEMSTATS_SLOTLIST slotmask) { if ((valid_slots & slotmask)==slotmask) return true; return false; } float psItemStats::GetDecayRate() { return decay_rate; } const char *psItemStats::GetMeshName() { return mesh_name; } void psItemStats::SetMeshName(const char *v) { mesh_name=v; } const char *psItemStats::GetTextureName() { return texture_name; } void psItemStats::SetTextureName(const char *v) { texture_name=v; } const char *psItemStats::GetPartName() { return texturepart_name; } void psItemStats::SetPartName(const char *v) { texturepart_name=v; } const char *psItemStats::GetPartMeshName() { return partmesh_name; } void psItemStats::SetPartMeshName(const char *v) { partmesh_name=v; } const char *psItemStats::GetImageName() { return image_name; } void psItemStats::SetImageName(const char *v) { image_name=v; } void psItemStats::SetPrice(int trias) { price = psMoney(trias); } psMoney& psItemStats::GetPrice() { return price; } void psItemStats::SetCategory(psItemCategory * item_category) { category = item_category; } psItemCategory * psItemStats::GetCategory() { return category; } const char *psItemStats::GetSound() { return sound; } void psItemStats::SetSound(const char *v) { sound = csString("item.") + v; } bool psItemStats::CheckRequirements( psCharacter* charData, csString& resp ) { float val = 0; csString needed = "You need to have "; bool first= true; for ( int z = 0; z < 3; z++ ) { PSITEMSTATS_STAT stat = CacheManager::GetSingleton().ConvertAttributeString(reqs[z].name); if ( stat != PSITEMSTATS_STAT_NONE ) { // Stat buffs may be negative; don't use those here bool usebuff = charData->GetAttributes()->GetBuffVal(stat) > 0; val = charData->GetAttributes()->GetStat(stat,usebuff); // TODO: This should just use the buff always when a move from equipment to bulk can't fail } else { PSSKILL skill = CacheManager::GetSingleton().ConvertSkillString(reqs[z].name); if ( skill != PSSKILL_NONE ) { val = charData->GetSkills()->GetSkillRank( skill ); } } if ( val < reqs[z].min_value ) { if(!first) needed +=" and "; else first = false; if(reqs[z].min_value - val > 40) needed += "a lot "; needed += "more in "; needed += reqs[z].name; } } if(first) // No needed things { resp = "None"; return true; } needed.Append(" to equip this item"); resp = needed; return false; } bool psItemStats::SetRequirement( csString* statName, float statValue ) { // The Stat already exists for ( int z = 0; z < 3; z++ ) { if ( reqs[z].name.IsEmpty() ) continue; if ( statName->CompareNoCase( reqs[z].name ) && reqs[z].min_value < statValue ) { reqs[z].min_value = statValue; return true; } } // The Stat didn't exist for ( int z = 0; z < 3; z++ ) { if ( reqs[z].name.IsEmpty() ) { reqs[z].name = statName->GetData(); reqs[z].min_value = statValue; return true; } } // No Space Available return false; } psItem *psItemStats::InstantiateBasicItem(bool transient) { psItem *newitem; if (this->GetIsGlyph()) { newitem = new psGlyph(); } else { newitem = new psItem(); } newitem->SetBaseStats(this); newitem->SetCurrentStats(this); if (transient) newitem->ScheduleRemoval(); // Remove from world in a few hrs if no one picks it up newitem->SetCreator(ITEM_BASIC); return newitem; // MUST do newitem->Loaded() when it is safe to save! } bool psItemStats::SetAttribute( csString* op, csString* attrName, float modifier) { csString Operation = op->GetData(), AttributeName = attrName->GetData(); float* value[5] = { NULL, NULL, NULL, NULL, NULL }; // Attribute Names: // item // weight // damage // slash // pierce // blunt // ... // protection // slash // pierce // blunt // ... // speed // target // wielder AttributeName.Downcase(); if ( AttributeName.Compare( "item.weight" ) ) { value[0] = &this->weight; } else if ( AttributeName.Compare( "item.damage_value" ) ) { value[0] = 0; } else if ( AttributeName.Compare( "item.attack_value" ) ) { value[0] = 0; } else if ( AttributeName.Compare( "item.speed" ) ) { value[0] = &this->weaponStats.latency; } else if ( AttributeName.Compare( "item.damage" ) ) { value[0] = &this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_SLASH]; value[1] = &this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_BLUNT]; value[2] = &this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_PIERCE]; } else if ( AttributeName.Compare( "item.damage.slash" ) ) { value[0] = &this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_SLASH]; } else if ( AttributeName.Compare( "item.damage.pierce" ) ) { value[0] = &this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_PIERCE]; } else if ( AttributeName.Compare( "item.damage.blunt" ) ) { value[0] = &this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_BLUNT]; } else if ( AttributeName.Compare( "item.damage.force" ) ) { value[0] = &this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_FORCE]; } else if ( AttributeName.Compare( "item.damage.fire" ) ) { value[0] = &this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_FIRE]; } else if ( AttributeName.Compare( "item.damage.ice" ) ) { value[0] = &this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_ICE]; } else if ( AttributeName.Compare( "item.damage.air" ) ) { value[0] = &this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_AIR]; } else if ( AttributeName.Compare( "item.damage.poison" ) ) { value[0] = &this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_POISON]; } else if ( AttributeName.Compare( "item.damage.disease" ) ) { value[0] = &this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_DISEASE]; } else if ( AttributeName.Compare( "item.damage.holy" ) ) { value[0] = &this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_HOLY]; } else if ( AttributeName.Compare( "item.damage.unholy" ) ) { value[0] = &this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_UNHOLY]; } else if ( AttributeName.Compare( "item.protection" ) ) { value[0] = &this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_SLASH]; value[1] = &this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_BLUNT]; value[2] = &this->weaponStats.damages[PSITEMSTATS_DAMAGETYPE_PIERCE]; } else if ( AttributeName.Compare( "item.protection.slash" ) ) { value[0] = &this->armorStats.damage_protection[PSITEMSTATS_DAMAGETYPE_SLASH]; } else if ( AttributeName.Compare( "item.protection.pierce" ) ) { value[0] = &this->armorStats.damage_protection[PSITEMSTATS_DAMAGETYPE_PIERCE]; } else if ( AttributeName.Compare( "item.protection.blunt" ) ) { value[0] = &this->armorStats.damage_protection[PSITEMSTATS_DAMAGETYPE_BLUNT]; } else if ( AttributeName.Compare( "item.protection.force" ) ) { value[0] = &this->armorStats.damage_protection[PSITEMSTATS_DAMAGETYPE_FORCE]; } else if ( AttributeName.Compare( "item.protection.fire" ) ) { value[0] = &this->armorStats.damage_protection[PSITEMSTATS_DAMAGETYPE_FIRE]; } else if ( AttributeName.Compare( "item.protection.ice" ) ) { value[0] = &this->armorStats.damage_protection[PSITEMSTATS_DAMAGETYPE_ICE]; } else if ( AttributeName.Compare( "item.protection.air" ) ) { value[0] = &this->armorStats.damage_protection[PSITEMSTATS_DAMAGETYPE_AIR]; } else if ( AttributeName.Compare( "item.protection.poison" ) ) { value[0] = &this->armorStats.damage_protection[PSITEMSTATS_DAMAGETYPE_POISON]; } else if ( AttributeName.Compare( "item.protection.disease" ) ) { value[0] = &this->armorStats.damage_protection[PSITEMSTATS_DAMAGETYPE_DISEASE]; } else if ( AttributeName.Compare( "item.protection.holy" ) ) { value[0] = &this->armorStats.damage_protection[PSITEMSTATS_DAMAGETYPE_HOLY]; } else if ( AttributeName.Compare( "item.protection.unholy" ) ) { value[0] = &this->armorStats.damage_protection[PSITEMSTATS_DAMAGETYPE_UNHOLY]; } // Operations = ADD, MUL, SET for ( int i = 0; i < 5; i++ ) { if ( Operation.CompareNoCase( "ADD" ) ) { if (value[i]) *value[i] += modifier; } if ( Operation.CompareNoCase( "MUL" ) ) { if (value[i]) *value[i] *= modifier; } if ( Operation.CompareNoCase( "VAL" ) ) { if (value[i]) *value[i] = modifier; } } return true; }