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/>.
17 // precompiled headers must be first
21 #include "nel/misc/variable.h"
24 #include "death_penalties.h"
25 #include "player_manager/character.h"
26 #include "phrase_manager/phrase_utilities_functions.h"
27 #include "player_manager/item_service_manager.h"
28 #include "server_share/r2_variables.h"
30 NL_INSTANCE_COUNTER_IMPL(CDeathPenalties
);
32 NLMISC::CVariable
<bool> DissableDPInRing("egs", "DissableDPInRing", "Enable or dissable DP system in the Ring (should be dissabled unless this provokes bugs", true,0,true);
34 void CDeathPenalties::updataDb(CCharacter
& user
)
36 if ( _DeathXPToGain
== 0 )
37 // user._PropertyDatabase.setProp( "USER:DEATH_XP_MALUS", 255 );
38 CBankAccessor_PLR::getUSER().setDEATH_XP_MALUS(user
._PropertyDatabase
, 255 );
40 // user._PropertyDatabase.setProp( "USER:DEATH_XP_MALUS", uint8( 254 * (1 - _CurrentDeathXP / _DeathXPToGain ) ) );
41 CBankAccessor_PLR::getUSER().setDEATH_XP_MALUS(user
._PropertyDatabase
, checkedCast
<uint8
>( 254 * (1 - _CurrentDeathXP
/ _DeathXPToGain
) ) );
44 void CDeathPenalties::addDeath(CCharacter
& user
, float deathPenaltyFactor
)
46 // we don't add death penalty in the ring
47 if (IsRingShard
&& DissableDPInRing
)
52 // note that NB death is no more useful, but we keep it in serial until we have a better serial system
53 SKILLS::ESkills expSkill
;
54 double maxXP
= user
.getSkills().getMaxXPToGain(expSkill
);
57 const double maxMalus
= maxXP
* user
.getSkillBaseValue(expSkill
);
58 double xpMalus
= ((double)deathPenaltyFactor
) * DeathXPFactor
* maxMalus
;
60 if ( xpMalus
+ _DeathXPToGain
<= maxMalus
)
61 _DeathXPToGain
+= xpMalus
;
65 xpMalus
-= (maxMalus
- _DeathXPToGain
);
66 _DeathXPToGain
= maxMalus
;
68 // remove penalty surplus from already paid back Xp debt
69 if ( _CurrentDeathXP
>= xpMalus
)
70 _CurrentDeathXP
-= xpMalus
;
72 _CurrentDeathXP
= 0.0;
76 if( _CurrentDeathXP
|| _DeathXPToGain
)
78 SM_STATIC_PARAMS_2(params
,STRING_MANAGER::integer
,STRING_MANAGER::integer
);
79 params
[0].Int
= sint32(10*_CurrentDeathXP
);
80 params
[1].Int
= sint32(10*_DeathXPToGain
);
81 CCharacter::sendDynamicSystemMessage( user
.getId(),"DEATH_XP_DEATH",params
);
85 uint32
CDeathPenalties::updateResorption( CCharacter
& user
)
87 // we don't add death penalty in the ring
88 if (IsRingShard
&& DissableDPInRing
)
93 uint32 currentTime
= NLMISC::CTime::getSecondsSince1970();
94 if ( _NbDeath
&& _BonusUpdateTime
!=0 && _BonusUpdateTime
<currentTime
)
96 SKILLS::ESkills expSkill
;
97 double maxXP
= user
.getSkills().getMaxXPToGain(expSkill
);
99 double timeFactor
= (double)(currentTime
- _BonusUpdateTime
) / (60.*60.*24. * user
.getDPLossDuration());
101 const double maxMalus
= maxXP
* user
.getSkillBaseValue(expSkill
);
102 double xpBonus
= ((double)timeFactor
) * maxMalus
;
104 addXP(user
, SKILLS::unknown
, xpBonus
, xpBonus
);
106 _BonusUpdateTime
= currentTime
;
113 void CDeathPenalties::addXP( CCharacter
& user
, SKILLS::ESkills usedSkill
, double & xp
)
115 // we don't add death penalty in the ring
116 if (IsRingShard
&& DissableDPInRing
)
123 // we multiply gained xp by used skill level
124 SKILLS::ESkills expSkill
;
125 user
.getSkills().getMaxXPToGain(expSkill
);
126 const double skillBaseValue
= user
.getSkillBaseValue(expSkill
);
127 if (skillBaseValue
<= 0)
129 nlwarning("Skill %s base value for char %s is <= 0 !!",SKILLS::toString(expSkill
).c_str(), user
.getId().toString().c_str());
134 double xpBeforeDeathPenalty
= xp
;
135 double xpUsedForDeathPenalty
= xp
* _DeathPenaltyFactor
;
136 SSkill
* skill
= user
.getSkills().getSkillStruct(usedSkill
);
137 if (skill
->MaxLvlReached
< 250)
138 xpUsedForDeathPenalty
*= 0.5f
;
140 xp
-= xpUsedForDeathPenalty
;
142 double tempXp
= xpUsedForDeathPenalty
* skillBaseValue
;
143 addXP(user
, usedSkill
, tempXp
, xpBeforeDeathPenalty
);
144 xpUsedForDeathPenalty
= tempXp
/ skillBaseValue
;
146 xp
+= xpUsedForDeathPenalty
;
150 void CDeathPenalties::addXP( CCharacter
& user
, SKILLS::ESkills usedSkill
, double & xp
, double xpRaw
)
152 // we don't add death penalty in the ring
153 if (IsRingShard
&& DissableDPInRing
)
158 _CurrentDeathXP
+= xp
;
160 if ( _CurrentDeathXP
>= _DeathXPToGain
)
162 // no more death penalties, only keep the xp surplus
163 xp
= _CurrentDeathXP
- _DeathXPToGain
;
167 PHRASE_UTILITIES::sendDynamicSystemMessage(user
.getEntityRowId(), "PROGRESS_DEATH_PENALTY_COMPLETE");
169 // consume SpeedUpDPLoss services
172 const CStaticItem
* form
= CItemServiceManager::getInstance()->removePersistentService(ITEM_SERVICE_TYPE::SpeedUpDPLoss
, &user
);
176 SM_STATIC_PARAMS_1(params
, STRING_MANAGER::item
);
177 params
[0].SheetId
= form
->SheetId
;
178 PHRASE_UTILITIES::sendDynamicSystemMessage(user
.getEntityRowId(), "ITEM_SERVICE_CONSUMED", params
);
183 // Don't send message to user if the xp was penalty resorption
184 if (usedSkill
!=SKILLS::unknown
)
186 SM_STATIC_PARAMS_4(params
, STRING_MANAGER::integer
, STRING_MANAGER::skill
, STRING_MANAGER::integer
, STRING_MANAGER::integer
);
187 params
[0].Int
= sint32(100*xpRaw
);
188 params
[1].Enum
= usedSkill
;
189 params
[2].Int
= sint32(10*xp
);
190 params
[3].Int
= sint32(10*(_DeathXPToGain
-_CurrentDeathXP
) );
191 PHRASE_UTILITIES::sendDynamicSystemMessage(user
.getEntityRowId(), "PROGRESS_DEATH_PENALTY_PAYBACK", params
);
199 CDeathPenaltiesTimerEvent::CDeathPenaltiesTimerEvent(CCharacter
*parent
)
204 void CDeathPenaltiesTimerEvent::timerCallback(CTimer
* owner
)
206 H_AUTO(CDeathPenaltiesTimerEvent
);
208 uint32 nextUpdate
= _Parent
->updateDeathPenaltyResorption();
209 owner
->setRemaining(nextUpdate
, this);