1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
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.
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/>.
21 #include "nel/misc/command.h"
23 #include "game_share/tick_event_handler.h"
25 #include "sabrina_item_stats.h"
28 using namespace NLMISC
;
31 //--------------------------------------------------------------
33 //--------------------------------------------------------------
35 bool UseWeaponDamageFactorModifier
= true;
38 //--------------------------------------------------------------
40 //--------------------------------------------------------------
50 const CHitChance TableChanceMeleeHitByAdversaryLevel
[]=
67 const CHitChance TableChanceSpellHitByAdversaryLevel
[]=
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
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
127 int PercentProtection
;
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()
169 _DmgType
= DMGTYPE::UNDEFINED
;
170 _Skill
= SKILLS::unknown
;
171 _Family
= ITEMFAMILY::UNDEFINED
;
174 CWeaponStats::CWeaponStats(const CGameItemPtr
&itemPtr
,uint16 quality
)
180 _DmgType
= DMGTYPE::UNDEFINED
;
181 _Skill
= SKILLS::unknown
;
182 _Family
= ITEMFAMILY::UNDEFINED
;
184 if (itemPtr
== NULL
|| itemPtr
->getStaticForm() == NULL
)
187 _Family
= itemPtr
->getStaticForm()->Family
;
191 case ITEMFAMILY::MELEE_WEAPON
:
192 if (!itemPtr
->getStaticForm()->MeleeWeapon
)
194 _DmgType
= itemPtr
->getStaticForm()->MeleeWeapon
->DamageType
;
195 _Skill
= itemPtr
->getStaticForm()->Skill
;
198 case ITEMFAMILY::RANGE_WEAPON
:
199 if (!itemPtr
->getStaticForm()->RangeWeapon
)
201 _DmgType
= itemPtr
->getStaticForm()->RangeWeapon
->DamageType
;
202 _Skill
= itemPtr
->getStaticForm()->Skill
;
203 _Range
= itemPtr
->getRange();
206 case ITEMFAMILY::AMMO
:
207 if (!itemPtr
->getStaticForm()->Ammo
)
209 _DmgType
= itemPtr
->getStaticForm()->Ammo
->DamageType
;
210 _Range
= itemPtr
->getRange();
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);
228 _Damage
= itemPtr
->getDamage();
231 // SkillValue must be init in the calling class
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() );
244 //--------------------------------------------------------------
245 // CArmouStats methods
246 //--------------------------------------------------------------
247 CArmorStats::CArmorStats()
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
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
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
;
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
;
292 nlwarning("CArmorStats::CArmorStats(): Unknown armor type %d, return 0", item
->Armor
->ArmorType
);
297 for (int i
=0;i
<DMGTYPE::NBTYPES
;++i
)
299 _ProtectionFactor
[i
]=percentProtect
;
300 _ProtectionLimit
[i
]=maxProtect
;
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
]);
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
);
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
);
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
);
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
);
364 _ProtectionLimit
[index
]=val
;
367 //--------------------------------------------------------------
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");