Resolve "Toggle Free Look with Hotkey"
[ryzomcore.git] / ryzom / server / src / sabrina / sabrina_item_stats.cpp
blob43ec71e375eba1b090ce906ad02e717e739783b1
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "stdpch.h"
20 // nel
21 #include "nel/misc/command.h"
22 // game_share
23 #include "game_share/tick_event_handler.h"
24 // sabrina
25 #include "sabrina_item_stats.h"
27 using namespace std;
28 using namespace NLMISC;
31 //--------------------------------------------------------------
32 // Global Variables
33 //--------------------------------------------------------------
35 bool UseWeaponDamageFactorModifier = true;
38 //--------------------------------------------------------------
39 // Data Tables
40 //--------------------------------------------------------------
42 struct CHitChance
44 int DeltaLevel;
45 float PercentSuccess;
46 int MaxLevelBoost;
47 float XPMultiplier;
50 const CHitChance TableChanceMeleeHitByAdversaryLevel[]=
52 {7, 95.0f, 0, 2.1f},
53 {6, 95.0f, 0, 2.1f},
54 {5, 95.0f, 0, 2.1f},
55 {4, 90.0f, 0, 1.9f},
56 {3, 80.0f, 0, 1.7f},
57 {2, 70.0f, 0, 1.5f},
58 {1, 60.0f, 1, 1.2f},
59 {0, 50.0f, 0, 1.0f},
60 {-1, 40.0f, 0, 0.8f},
61 {-2, 30.0f, 0, 0.3f},
62 {-3, 20.0f, 0, 0.1f},
63 {-4, 10.0f, 0, 0.0f},
64 {-5, 5.0f, 0, 0.0f}
67 const CHitChance TableChanceSpellHitByAdversaryLevel[]=
69 {7, 95.0f, 0, 2.1f},
70 {6, 95.0f, 0, 2.1f},
71 {5, 95.0f, 0, 2.1f},
72 {4, 90.0f, 0, 1.9f},
73 {3, 80.0f, 0, 1.7f},
74 {2, 70.0f, 0, 1.5f},
75 {1, 60.0f, 1, 1.2f},
76 {0, 50.0f, 0, 1.0f},
77 {-1, 40.0f, 0, 0.8f},
78 {-2, 30.0f, 0, 0.3f},
79 {-3, 20.0f, 0, 0.1f},
80 {-4, 10.0f, 0, 0.0f},
81 {-5, 5.0f, 0, 0.0f}
84 // note on size modifiers
85 // attacker is smaller than defender +1
86 // attacker is a bit bigger -2
87 // attacker is much bigger -4
89 struct CWeaponGenerics
91 int Quality;
92 int RateOfFire;
93 float DamageFactor;
94 float SecondaryDamageFactor; // damage factor when entity level > weapon quality
97 const CWeaponGenerics TableMeleeWeaponGenerics[]=
99 // light weapon medium weapon heavy weapon
100 {1,1,6.0f,2.5f}, {1,1,8.0f,3.7f}, {1,1,17.92f,8.5f},
101 {2,1,3.75f,2.25f}, {2,1,5.0f,3.0f}, {2,1,11.2f,7.0f},
102 {3,1,3.0f,2.25f}, {3,1,4.0f,3.0f}, {3,1,8.96f,7.0f},
103 {4,1,2.25f,2.25f}, {4,1,3.0f,3.0f}, {4,1,6.72f,6.72f},
104 {5,1,2.25f,2.25f}, {5,1,3.0f,3.0f}, {5,1,6.72f,6.72f},
105 {6,1,2.25f,2.25f}, {6,1,3.0f,3.0f}, {6,1,6.72f,6.72f},
106 {7,1,2.25f,2.25f}, {7,1,3.0f,3.0f}, {7,1,6.72f,6.72f},
107 {8,1,3.0f,3.0f}, {8,1,4.0f,4.0f}, {8,1,8.96f,8.96f},
108 {9,1,3.0f,3.0f}, {9,1,4.0f,4.0f}, {9,1,8.96f,8.96f},
109 {10,1,3.0f,3.0f}, {10,1,4.0f,4.0f}, {10,1,8.96f,8.96f},
110 {11,1,3.75f,3.75f}, {11,1,5.0f,5.0f}, {11,1,11.2f,11.2f},
111 {12,1,3.75f,3.75f}, {12,1,5.0f,5.0f}, {12,1,11.2f,11.2f},
112 {13,1,3.75f,3.75f}, {13,1,5.0f,5.0f}, {13,1,11.2f,11.2f},
113 {14,1,4.5f,4.5f}, {14,1,6.0f,6.0f}, {14,1,13.44f,13.44f},
114 {15,1,5.25f,5.25f}, {15,1,7.0f,7.0f}, {15,1,15.68f,15.68f},
115 {16,1,6.0f,6.0f}, {16,1,8.0f,8.0f}, {16,1,17.92f,17.92f},
116 {17,1,6.75f,6.75f}, {17,1,9.0f,9.0f}, {17,1,20.16f,20.16f},
117 {18,1,7.5f,7.5f}, {18,1,10.0f,10.0f}, {18,1,22.4f,22.4f},
118 {19,1,8.25f,8.25f}, {19,1,11.0f,11.0f}, {19,1,24.64f,24.64f},
119 {20,1,9.75f,9.75f}, {20,1,13.0f,13.0f}, {20,1,29.12f,29.12f},
120 {21,1,11.25f,11.25f}, {21,1,15.0f,15.0f}, {21,1,33.6f,33.6f},
122 const uint32 NumWeaponGenerics= sizeof(TableMeleeWeaponGenerics)/(3*sizeof(TableMeleeWeaponGenerics[0]));
124 struct CArmorGenerics
126 int Quality ;
127 int PercentProtection;
128 int MaxProtection ;
131 const CArmorGenerics TableArmorGenerics[]=
133 // light medium heavy
134 {1,20,2}, {1,35,3}, {1,50,4},
135 {2,20,2}, {2,35,3}, {2,50,5},
136 {3,20,2}, {3,35,4}, {3,50,6},
137 {4,20,3}, {4,35,5}, {4,50,7},
138 {5,20,3}, {5,35,6}, {5,50,8},
139 {6,20,4}, {6,35,7}, {6,50,10},
140 {7,20,5}, {7,35,8}, {7,50,12},
141 {8,20,6}, {8,35,10}, {8,50,14},
142 {9,20,7}, {9,35,12}, {9,50,17},
143 {10,20,8}, {10,35,14}, {10,50,21},
144 {11,20,10}, {11,35,17}, {11,50,25},
145 {12,20,12}, {12,35,21}, {12,50,30},
146 {13,20,14}, {13,35,25}, {13,50,36},
147 {14,20,17}, {14,35,30}, {14,50,43},
148 {15,20,21}, {15,35,36}, {15,50,51},
149 {16,20,25}, {16,35,43}, {16,50,62},
150 {17,20,30}, {17,35,52}, {17,50,74},
151 {18,20,35}, {18,35,62}, {18,50,89},
152 {19,20,43}, {19,35,75}, {19,50,106},
153 {20,20,51}, {20,35,89}, {20,50,128},
154 {21,20,61}, {21,35,107}, {21,50,153},
156 const uint32 NumArmorGenerics= sizeof(TableArmorGenerics)/(3*sizeof(TableArmorGenerics[0]));
159 //--------------------------------------------------------------
160 // CWeaponStats methods
161 //--------------------------------------------------------------
163 CWeaponStats::CWeaponStats()
165 _SpeedInTicks = 0;
166 _Damage = 0;
167 _Quality = 0;
168 _Range = 0;
169 _DmgType = DMGTYPE::UNDEFINED;
170 _Skill = SKILLS::unknown;
171 _Family = ITEMFAMILY::UNDEFINED;
174 CWeaponStats::CWeaponStats(const CGameItemPtr &itemPtr,uint16 quality)
176 _SpeedInTicks = 0;
177 _Damage = 0;
178 _Quality = quality;
179 _Range = 0;
180 _DmgType = DMGTYPE::UNDEFINED;
181 _Skill = SKILLS::unknown;
182 _Family = ITEMFAMILY::UNDEFINED;
184 if (itemPtr == NULL || itemPtr->getStaticForm() == NULL )
185 return;
187 _Family = itemPtr->getStaticForm()->Family;
189 switch(_Family)
191 case ITEMFAMILY::MELEE_WEAPON:
192 if (!itemPtr->getStaticForm()->MeleeWeapon)
193 return;
194 _DmgType = itemPtr->getStaticForm()->MeleeWeapon->DamageType;
195 _Skill = itemPtr->getStaticForm()->Skill;
196 break;
198 case ITEMFAMILY::RANGE_WEAPON:
199 if (!itemPtr->getStaticForm()->RangeWeapon)
200 return;
201 _DmgType = itemPtr->getStaticForm()->RangeWeapon->DamageType;
202 _Skill = itemPtr->getStaticForm()->Skill;
203 _Range = itemPtr->getRange();
204 break;
206 case ITEMFAMILY::AMMO:
207 if (!itemPtr->getStaticForm()->Ammo)
208 return;
209 _DmgType = itemPtr->getStaticForm()->Ammo->DamageType;
210 _Range = itemPtr->getRange();
211 break;
213 default:
214 break;
217 if (_Skill == SKILLS::unknown)
219 nlwarning("<CCombatWeapon::CCombatWeapon> Error : item %s skill is Unknown", itemPtr->getStaticForm()->Name.c_str());
222 _SpeedInTicks = uint16(itemPtr->getSpeed() / CTickEventHandler::getGameTimeStep());
223 _Quality = itemPtr->quality();
225 if ( UseWeaponDamageFactorModifier )
226 _Damage = itemPtr->getDamage() * 260 / (10 + _Quality*10);
227 else
228 _Damage = itemPtr->getDamage();
231 // SkillValue must be init in the calling class
232 _SkillValue = 0;
233 } // CCombatWeapon //
235 std::string CWeaponStats::toString() const
237 const std::string temp =
238 NLMISC::toString("Damage = %u, Quality = %u, SkillValue = %u, dmgType = %s, Family = %s",
239 _Damage, _Quality, _SkillValue,DMGTYPE::toString(_DmgType).c_str(), ITEMFAMILY::toString(_Family).c_str() );
240 return temp;
244 //--------------------------------------------------------------
245 // CArmouStats methods
246 //--------------------------------------------------------------
247 CArmorStats::CArmorStats()
249 _Quality=0;
250 _Skill=SKILLS::unknown;
251 _ArmorType=ARMORTYPE::UNKNOWN;
252 for (int i=0;i<DMGTYPE::NBTYPES;++i)
254 _ProtectionFactor[i]=0;
255 _ProtectionLimit[i]=0;
259 CArmorStats::CArmorStats( const CStaticItem *item, uint16 quality )
261 // initialise just like default constructor just in case we find an invalid item and decide to return
262 _Quality=0;
263 _Skill=SKILLS::unknown;
264 _ArmorType=ARMORTYPE::UNKNOWN;
265 for (int i=0;i<DMGTYPE::NBTYPES;++i)
267 _ProtectionFactor[i]=0;
268 _ProtectionLimit[i]=0;
270 // make sure the item is valid
271 if (!item || !item->Armor) return;
273 // the item was valid so retrieve in the correct item stats
274 _Quality = quality;
275 _ArmorType = item->Armor->ArmorType;
276 _Skill = item->Skill;
278 // getArmorCharacteristics
279 uint32 tblIdx= (quality==0)? 0: (quality >= NumArmorGenerics)? NumArmorGenerics*3: quality*3;
280 uint8 percentProtect;
281 uint16 maxProtect;
282 switch(item->Armor->ArmorType)
284 case ARMORTYPE::HEAVY: ++tblIdx;
285 case ARMORTYPE::MEDIUM: ++tblIdx;
286 case ARMORTYPE::LIGHT:
287 percentProtect= TableArmorGenerics[tblIdx].PercentProtection;
288 maxProtect= TableArmorGenerics[tblIdx].MaxProtection;
289 break;
291 default:
292 nlwarning("CArmorStats::CArmorStats(): Unknown armor type %d, return 0", item->Armor->ArmorType);
293 percentProtect = 0;
294 maxProtect = 0;
297 for (int i=0;i<DMGTYPE::NBTYPES;++i)
299 _ProtectionFactor[i]=percentProtect;
300 _ProtectionLimit[i]=maxProtect;
302 } // CCombatArmor //
304 std::string CArmorStats::toString(bool overrideTitle) const
306 std::string result= overrideTitle? "": "Armor";
307 result+=NLMISC::toString(": %s,",ARMORTYPE::armorTypeToString(_ArmorType));
308 result+=NLMISC::toString(", Quality: %d",_Quality);
309 result+=NLMISC::toString(", Skill: %s",SKILLS::toString(_Skill));
310 for (sint16 i=0;i<DMGTYPE::NBTYPES;++i)
311 result+=NLMISC::toString(", %s(%d,%d)",DMGTYPE::toString((DMGTYPE::EDamageType)i),_ProtectionFactor[i],_ProtectionLimit[i]);
312 return result;
315 float CArmorStats::getProtectionFactor(uint32 index) const
317 if (index>=DMGTYPE::NBTYPES)
319 nlwarning("BUG: getProtectionFactor(uint32 index): index out of bounds: %d (should be < %d)",index,DMGTYPE::NBTYPES);
320 #ifdef NL_DEBUG
321 nlstop
322 #endif
323 return 0;
325 return _ProtectionFactor[index];
328 uint32 CArmorStats::getProtectionLimit(uint32 index) const
330 if (index>=DMGTYPE::NBTYPES)
332 nlwarning("BUG: getProtectionLimit(uint32 index): index out of bounds: %d (should be < %d)",index,DMGTYPE::NBTYPES);
333 #ifdef NL_DEBUG
334 nlstop
335 #endif
336 return 0;
338 return _ProtectionLimit[index];
341 void CArmorStats::setProtectionFactor(uint32 index,float val)
343 if (index>=DMGTYPE::NBTYPES)
345 nlwarning("BUG: setProtectionFactor(): index out of bounds: %d (should be < %d)",index,DMGTYPE::NBTYPES);
346 #ifdef NL_DEBUG
347 nlstop
348 #endif
349 return;
351 _ProtectionFactor[index]=val;
354 void CArmorStats::setProtectionLimit(uint32 index,uint32 val)
356 if (index>=DMGTYPE::NBTYPES)
358 nlwarning("BUG: setProtectionLimit(): index out of bounds: %d (should be < %d)",index,DMGTYPE::NBTYPES);
359 #ifdef NL_DEBUG
360 nlstop
361 #endif
362 return;
364 _ProtectionLimit[index]=val;
367 //--------------------------------------------------------------
368 // NLMISC COMMANDS
369 //--------------------------------------------------------------
371 NLMISC_COMMAND(UseWeaponDamageFactorModifier,"toggle the use of the item damage factor (temporary patch item damage )","")
373 UseWeaponDamageFactorModifier = !UseWeaponDamageFactorModifier;
375 log.displayNL("UseWeaponDamageFactorModifier is %s",UseWeaponDamageFactorModifier?"used":"unused");
376 return true;