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/>.
20 #include "magic_action.h"
21 #include "magic_phrase.h"
23 #include "character.h"
24 #include "phrase_utilities_functions.h"
25 #include "game_share/entity_structure/statistic.h"
26 #include "game_share/magic_fx.h"
28 #include "phrase_manager.h"
30 using namespace NLNET
;
31 using namespace NLMISC
;
32 using namespace RY_GAME_SHARE
;
35 std::vector
< std::pair
< std::string
, IMagicActionFactory
* > >* IMagicActionFactory::Factories
= NULL
;
38 class CMagicActionBasicDamage
: public IMagicAction
41 CMagicActionBasicDamage()
42 :_DmgHp(0),_DmgSap(0),_DmgSta(0),_DmgType(DMGTYPE::UNDEFINED
){}
44 virtual bool addBrick( const CStaticBrick
& brick
, CMagicPhrase
* phrase
, bool &effectEnd
)
46 for ( uint i
=0 ; i
<brick
.Params
.size() ; ++i
)
48 switch(brick
.Params
[i
]->id())
50 case TBrickParam::MA_END
:
51 INFOLOG("MA_END Found: end of effect");
55 case TBrickParam::MA_DMG_TYPE
:
56 INFOLOG("MA_DMG_TYPE: %s",((CSBrickParamMagicDmgType
*)brick
.Params
[i
])->DmgType
.c_str());
57 _DmgType
= DMGTYPE::stringToDamageType( ((CSBrickParamMagicDmgType
*)brick
.Params
[i
])->DmgType
);
58 if ( _DmgType
== DMGTYPE::UNDEFINED
)
60 nlwarning("<CMagicActionBasicDamage addBrick> invalid dmg type %s", ((CSBrickParamMagicDmgType
*)brick
.Params
[i
])->DmgType
.c_str());
65 case TBrickParam::MA_DMG
:
66 INFOLOG("MA_DMG: %u %u %u",((CSBrickParamMagicDmg
*)brick
.Params
[i
])->Hp
,((CSBrickParamMagicDmg
*)brick
.Params
[i
])->Sap
,((CSBrickParamMagicDmg
*)brick
.Params
[i
])->Sta
);
67 _DmgHp
= ((CSBrickParamMagicDmg
*)brick
.Params
[i
])->Hp
;
68 _DmgSap
= ((CSBrickParamMagicDmg
*)brick
.Params
[i
])->Sap
;
69 _DmgSta
= ((CSBrickParamMagicDmg
*)brick
.Params
[i
])->Sta
;
73 // unused param, can be useful in the phrase
74 phrase
->applyBrickParam( brick
.Params
[i
] );
78 ///\todo nico: check if everything is set
81 virtual bool validate(CMagicPhrase
* phrase
)
83 return PHRASE_UTILITIES::validateSpellTarget(phrase
->getActor(),phrase
->getTargets()[0],ACTNATURE::OFFENSIVE
);
85 virtual void apply( CMagicPhrase
* phrase
, float successFactor
,MBEHAV::CBehaviour
& behav
, bool isMad
)
90 // - player damages + on armor
91 // - behaviour + chat messages
94 CEntityBase
* actor
= CEntityBaseManager::getEntityBasePtr( phrase
->getActor() );
99 if ( successFactor
<= 0.0f
)
101 if ( actor
->getId().getType() == RYZOMID::player
)
102 CCharacter::sendMessageToClient( actor
->getId(),"MAGIC_TOTAL_MISS" );
106 const std::vector
< TDataSetRow
> & targets
= phrase
->getTargets();
108 SSkill
* skillAtt
= actor
->getSkills().getSkillStruct( _Skill
);
111 nlwarning("<CMagicActionBasicDamage apply> %s is not a valid skill",SKILLS::toString(_Skill
).c_str());
115 const CSEffect
* debuff
= actor
->lookForSEffect( EFFECT_FAMILIES::DebuffSkillMagic
);
116 sint skillValue
= skillAtt
->Current
;
118 skillValue
-= debuff
->getParamValue();
120 for ( uint i
= 0; i
< targets
.size(); i
++ )
123 CEntityBase
* target
= CEntityBaseManager::getEntityBasePtr( targets
[i
] );
126 if ( isMad
|| PHRASE_UTILITIES::validateSpellTarget(actor
->getEntityRowId(),target
->getEntityRowId(),ACTNATURE::OFFENSIVE
) )
129 //behav.Magic.SpellPower = PHRASE_UTILITIES::getAttackIntensity( phrase->getSabrinaCost() );
133 /* SSkill * skillResist = target->getSkills().getSkillStruct( SKILLS::MagicDefense ); //TODO skill missing
136 nlwarning("<CMagicActionBasicDamage apply> MagicDefense is not a valid skill");
139 */ // get the chances ( delta level is divided by 10 because a level is 10
140 const uint8 chances
= PHRASE_UTILITIES::getSuccessChance( ( skillValue
/*- skillResist->Current*/ )/10 ); //TODO skillResist
141 const uint8 roll
= (uint8
)RandomGenerator
.rand( 99 );
142 float resistFactor
= PHRASE_UTILITIES::getSucessFactor(chances
, roll
);
144 if ( resistFactor
> 0.0f
)
146 if ( resistFactor
> 1.0f
)
148 //behav.Spell.Resist = 0;
149 behav
.Spell
.SpellId
= MAGICFX::toMagicFx( _DmgType
,false);
151 float mult
= resistFactor
;
152 const CSEffect
* effect
= target
->lookForSEffect( EFFECT_FAMILIES::MagicDmgAmpli
);
154 mult
*= ( effect
->getParamValue() / 100.0f
);
156 sint32 realDmgHp
= sint32 ( _DmgHp
* mult
);
157 realDmgHp
= sint32( target
->applyDamageOnArmor( _DmgType
, realDmgHp
) );
158 if ( target
->changeCurrentHp( - realDmgHp
) )
160 // send mission event
161 if ( actor
->getId().getType()== RYZOMID::player
)
163 CMissionEventKill
event ( target
->getEntityRowId() );
164 ((CCharacter
*) actor
)->processMissionEvent( event
);
167 if ( target
->getScores()._PhysicalScores
[SCORES::hit_points
].Current
<= 0)
169 target
->getScores()._PhysicalScores
[SCORES::hit_points
].Current
= 0;
170 //behav.Spell.KillingBlow = 1;
172 PHRASE_UTILITIES::sendScoreModifierSpellMessage( actor
, target
, realDmgHp
,SCORES::hit_points
, ACTNATURE::OFFENSIVE
);
176 RY_GAME_SHARE::SCharacteristicsAndScores
&score
= target
->getScores()._PhysicalScores
[SCORES::sap
];
177 realDmgSap
= sint32( _DmgSap
* mult
);
178 realDmgSap
= target
->applyDamageOnArmor( _DmgType
, realDmgSap
);
179 score
.Current
= score
.Current
- realDmgSap
;
180 if ( score
.Current
< 0)
182 PHRASE_UTILITIES::sendScoreModifierSpellMessage( actor
, target
, realDmgSap
,SCORES::sap
, ACTNATURE::OFFENSIVE
);
187 RY_GAME_SHARE::SCharacteristicsAndScores
&score
= target
->getScores()._PhysicalScores
[SCORES::stamina
];
188 realDmgSta
= sint32( _DmgSta
* mult
);
189 realDmgSta
= target
->applyDamageOnArmor( _DmgType
, realDmgSta
);
190 score
.Current
= score
.Current
- realDmgSta
;
191 if ( score
.Current
< 0)
193 PHRASE_UTILITIES::sendScoreModifierSpellMessage( actor
, target
, realDmgSta
,SCORES::stamina
, ACTNATURE::OFFENSIVE
);
196 ///\todo nico: real value
197 behav
.Spell
.SpellIntensity
= 5;
200 sint32 max
= target
->getPhysScores()._PhysicalScores
[SCORES::hit_points
].Max
;
203 const sint32 aggro
= (-1) * sint32((100.0 * float(realDmgHp
))/float(max
) );
205 CAiEventReport report
;
206 report
.AggroMul
= 1.0f
;
207 report
.AggroAdd
= aggro
;
208 report
.addDelta(AI_EVENT_REPORT::HitPoints
, (-1)*realDmgHp
);
209 CPhraseManager::getInstance()->addAiEventReport(report
);
212 max
= target
->getPhysScores()._PhysicalScores
[SCORES::sap
].Max
;
215 const sint32 aggro
= (-1) * sint32((100.0 * float(realDmgSap
))/float(max
) );
217 CAiEventReport report
;
218 report
.AggroMul
= 1.0f
;
219 report
.AggroAdd
= aggro
;
220 report
.addDelta(AI_EVENT_REPORT::Sap
, (-1)*realDmgSap
);
221 CPhraseManager::getInstance()->addAiEventReport(report
);
224 max
= target
->getPhysScores()._PhysicalScores
[SCORES::stamina
].Max
;
227 const sint32 aggro
= (-1) * sint32((100.0 * float(realDmgSta
))/float(max
) );
229 CAiEventReport report
;
230 report
.AggroMul
= 1.0f
;
231 report
.AggroAdd
= aggro
;
232 report
.addDelta(AI_EVENT_REPORT::Stamina
, (-1)*realDmgSta
);
233 CPhraseManager::getInstance()->addAiEventReport(report
);
238 if ( actor
->getId().getType() == RYZOMID::player
)
239 CCharacter::sendMessageToClient( actor
->getId(),"MAGIC_TOTAL_RESIST" );
240 if ( target
->getId().getType() == RYZOMID::player
)
241 CCharacter::sendMessageToClient( target
->getId(),"MAGIC_U_TOTAL_RESIST" );
243 //behav.Spell.Resist = 1;
245 /// compute resist XP gain
246 /* if ( target->getId().getType() == RYZOMID::player && resistFactor < 1.0f)
248 ///\todo nico resistFactor is the quality factor of the action for xp
249 ((CCharacter*) target)->actionReport( actor, (skillResist->Current - skillValue)/10, ACTNATURE::DEFENSIVE, SKILLS::toString( SKILLS::MagicDefense ) );
254 DMGTYPE::EDamageType _DmgType
;
259 BEGIN_MAGIC_ACTION_FACTORY(CMagicActionBasicDamage
)
260 ADD_MAGIC_ACTION_TYPE( "mto" )
261 END_MAGIC_ACTION_FACTORY(CMagicActionBasicDamage
)