2018-04-25 19:28:00 -07:00
2019-07-07 20:56:15 +00:00
# include <StdAfx.h>
2018-04-25 19:28:00 -07:00
# include "WeenieObject.h"
# include "ManaStone.h"
# include "Player.h"
2018-07-31 12:45:14 +01:00
# include <queue>
2018-04-25 19:28:00 -07:00
CManaStoneWeenie : : CManaStoneWeenie ( )
{
SetName ( " ManaStone " ) ;
m_Qualities . m_WeenieType = ManaStone_WeenieType ;
}
CManaStoneWeenie : : ~ CManaStoneWeenie ( )
{
}
void CManaStoneWeenie : : ApplyQualityOverrides ( )
{
}
2018-07-31 12:45:14 +01:00
struct CompareManaNeeds //: public std::function<CWeenieObject*, CWeenieObject*, bool>
{
bool operator ( ) ( CWeenieObject * left , CWeenieObject * right )
{
// comparator for making a min-heap based on remaining mana
return ( ( left - > InqIntQuality ( ITEM_MAX_MANA_INT , 0 , TRUE ) - left - > InqIntQuality ( ITEM_CUR_MANA_INT , - 1 , TRUE ) )
> ( right - > InqIntQuality ( ITEM_MAX_MANA_INT , 0 , TRUE ) - right - > InqIntQuality ( ITEM_CUR_MANA_INT , - 1 , TRUE ) ) ) ;
}
} ;
2018-07-12 14:41:21 -07:00
int CManaStoneWeenie : : UseWith ( CPlayerWeenie * player , CWeenieObject * with )
2018-04-25 19:28:00 -07:00
{
CManaStoneUseEvent * useEvent = new CManaStoneUseEvent ;
useEvent - > _target_id = with - > GetID ( ) ;
useEvent - > _tool_id = GetID ( ) ;
useEvent - > _max_use_distance = 1.0 ; // todo: change to 0?
player - > ExecuteUseEvent ( useEvent ) ;
return WERROR_NONE ;
}
2018-07-31 12:45:14 +01:00
int CManaStoneWeenie : : DoUseWithResponse ( CWeenieObject * source , CWeenieObject * pTarget )
{
CPlayerWeenie * player = source - > AsPlayer ( ) ;
int targetType = pTarget - > InqIntQuality ( ITEM_TYPE_INT , 0 ) ;
if ( ! ( targetType & TYPE_ITEM ) & & ! ( targetType & TYPE_CREATURE ) )
{
player - > SendTextToOverlay ( csprintf ( " You can't use %s on %s " , this - > GetName ( ) . c_str ( ) , pTarget - > GetName ( ) . c_str ( ) ) ) ; //todo: made up message, confirm if it's correct
return WERROR_NONE ;
}
int manaStoneCurrentMana = InqIntQuality ( ITEM_CUR_MANA_INT , - 1 , TRUE ) ;
double manaStoneDestroyChance = InqFloatQuality ( MANA_STONE_DESTROY_CHANCE_FLOAT , - 1 , TRUE ) ;
double manaStoneEfficiency = InqFloatQuality ( ITEM_EFFICIENCY_FLOAT , - 1 , TRUE ) ;
int targetCurrentMana = pTarget - > InqIntQuality ( ITEM_CUR_MANA_INT , - 1 , TRUE ) ;
int targetMaxMana = pTarget - > InqIntQuality ( ITEM_MAX_MANA_INT , - 1 , TRUE ) ;
if ( manaStoneCurrentMana < = 0 )
{
if ( targetType & TYPE_CREATURE | | targetCurrentMana < = 0 )
{
player - > SendTextToOverlay ( csprintf ( " You can't use %s on %s " , this - > GetName ( ) . c_str ( ) , pTarget - > GetName ( ) . c_str ( ) ) ) ; //todo: made up message, confirm if it's correct
return WERROR_NONE ;
}
if ( ! pTarget - > InqBoolQuality ( RETAINED_BOOL , FALSE ) )
{
int drainedMana = round ( targetCurrentMana * manaStoneEfficiency ) ;
m_Qualities . SetInt ( ITEM_CUR_MANA_INT , drainedMana ) ;
m_Qualities . SetInt ( UI_EFFECTS_INT , 1 ) ;
NotifyIntStatUpdated ( ITEM_CUR_MANA_INT , false ) ;
NotifyIntStatUpdated ( UI_EFFECTS_INT , false ) ;
pTarget - > Remove ( ) ;
RecalculateEncumbrance ( ) ;
// The Mana Stone drains 4,434 points of mana from the Pocket Watch.
// The Pocket Watch is destroyed.
player - > SendText ( csprintf ( " The %s drains %s points of mana from the %s. \n The %s is destroyed. " , GetName ( ) . c_str ( ) , FormatNumberString ( drainedMana ) . c_str ( ) , pTarget - > GetName ( ) . c_str ( ) , pTarget - > GetName ( ) . c_str ( ) ) , LTT_DEFAULT ) ;
}
else {
player - > SendTextToOverlay ( " That item is retained! " ) ; //todo: made up message, confirm if it's correct
return WERROR_BAD_PARAM ;
}
}
else
{
if ( targetType & TYPE_CREATURE ) // mana stone is being emptied into user, not filled
{
if ( pTarget - > id ! = player - > id )
{
// somehow not using on self. shouldn't be possible with the client. Made up message.
player - > SendText ( csprintf ( " You cannot use the %s on other creatures or players. " , GetName ( ) . c_str ( ) ) , LTT_DEFAULT ) ;
return WERROR_BAD_PARAM ;
}
std : : priority_queue < CWeenieObject * , std : : vector < CWeenieObject * > , CompareManaNeeds > itemsNeedingMana , itemsStillNeedingMana ; // MIN heaps sorted by mana deficit
for ( auto wielded : player - > m_Wielded )
{
int currentMana = wielded - > InqIntQuality ( ITEM_CUR_MANA_INT , 0 , TRUE ) ;
int maxMana = wielded - > InqIntQuality ( ITEM_MAX_MANA_INT , 0 , TRUE ) ;
int deficit = maxMana - currentMana ;
if ( deficit > 0 )
{
itemsNeedingMana . push ( wielded ) ;
}
}
2018-04-25 19:28:00 -07:00
2018-07-31 12:45:14 +01:00
if ( itemsNeedingMana . empty ( ) )
{
player - > SendText ( " None of your items need mana. " , LTT_DEFAULT ) ; // What's the correct text?
return WERROR_BAD_PARAM ;
}
int manaToDistribute = manaStoneCurrentMana ;
int manaDistributed = 0 ;
std : : set < CWeenieObject * > objectsReceivingMana ; // for the chatmessage at the end
2019-04-22 22:19:31 +00:00
manaToDistribute * = player - > m_Qualities . GetPositiveRating ( LUM_AUG_ITEM_MANA_GAIN_INT , false ) ;
2018-07-31 12:45:14 +01:00
while ( manaToDistribute > 0 & & ! itemsNeedingMana . empty ( ) )
{
CWeenieObject * item = itemsNeedingMana . top ( ) ;
itemsNeedingMana . pop ( ) ;
int itemMaxMana = item - > InqIntQuality ( ITEM_MAX_MANA_INT , 0 , TRUE ) ;
int itemCurrentMana = item - > InqIntQuality ( ITEM_CUR_MANA_INT , 0 , TRUE ) ;
int itemDeficit = itemMaxMana - itemCurrentMana ;
if ( manaToDistribute > = itemDeficit )
{
manaToDistribute - = itemDeficit ;
manaDistributed + = itemDeficit ;
item - > m_Qualities . SetInt ( ITEM_CUR_MANA_INT , itemMaxMana ) ;
}
else
{
int newManaAmount = itemCurrentMana + manaToDistribute ;
manaDistributed + = manaToDistribute ;
manaToDistribute = 0 ;
item - > m_Qualities . SetInt ( ITEM_CUR_MANA_INT , newManaAmount ) ;
itemsStillNeedingMana . push ( item ) ;
}
item - > NotifyIntStatUpdated ( ITEM_CUR_MANA_INT , false ) ;
objectsReceivingMana . insert ( item ) ;
}
std : : stringstream ss ;
bool first = true ;
ss < < csprintf ( " The %s gives %s points of mana to the following items: " , GetName ( ) . c_str ( ) , FormatNumberString ( manaDistributed ) . c_str ( ) ) ;
for ( auto item : objectsReceivingMana )
{
if ( first )
{
ss < < item - > GetName ( ) ;
first = false ;
continue ;
}
ss < < " , " ;
ss < < item - > GetName ( ) ;
}
ss < < " . " ;
player - > SendText ( ss . str ( ) . c_str ( ) , LTT_DEFAULT ) ;
int remainingDeficit = 0 ;
while ( ! itemsNeedingMana . empty ( ) )
{
remainingDeficit + = ( itemsNeedingMana . top ( ) - > InqIntQuality ( ITEM_MAX_MANA_INT , 0 , TRUE ) - itemsNeedingMana . top ( ) - > InqIntQuality ( ITEM_CUR_MANA_INT , 0 , TRUE ) ) ;
itemsNeedingMana . pop ( ) ;
}
while ( ! itemsStillNeedingMana . empty ( ) )
{
remainingDeficit + = ( itemsStillNeedingMana . top ( ) - > InqIntQuality ( ITEM_MAX_MANA_INT , 0 , TRUE ) - itemsStillNeedingMana . top ( ) - > InqIntQuality ( ITEM_CUR_MANA_INT , 0 , TRUE ) ) ;
itemsStillNeedingMana . pop ( ) ;
}
if ( remainingDeficit = = 0 )
{
player - > SendText ( " Your items are fully charged. " , LTT_DEFAULT ) ;
}
else
{
player - > SendText ( csprintf ( " You need %s more mana to fully charge your items. " , FormatNumberString ( remainingDeficit ) . c_str ( ) ) , LTT_DEFAULT ) ;
}
}
else // manastone being emptied into an item
{
if ( targetMaxMana < = 0 )
{
SendText ( csprintf ( " The %s does not require mana. " , pTarget - > GetName ( ) . c_str ( ) ) , LTT_DEFAULT ) ; //todo: made up message, confirm if it's correct
2019-10-27 17:56:36 +00:00
return WERROR_NONE ;
2018-07-31 12:45:14 +01:00
}
else if ( targetCurrentMana > = targetMaxMana )
{
SendText ( csprintf ( " The %s is already fully charged. " , pTarget - > GetName ( ) . c_str ( ) ) , LTT_DEFAULT ) ; //todo: made up message, confirm if it's correct
2019-10-27 17:56:36 +00:00
return WERROR_NONE ;
2018-07-31 12:45:14 +01:00
}
else
{
2019-10-27 17:56:36 +00:00
pTarget - > m_Qualities . SetInt ( ITEM_CUR_MANA_INT , min ( targetCurrentMana + manaStoneCurrentMana , targetMaxMana ) ) ;
pTarget - > NotifyIntStatUpdated ( ITEM_CUR_MANA_INT , false ) ;
player - > SendText ( csprintf ( " The %s gives %s points of mana to the %s. " , GetName ( ) . c_str ( ) , FormatNumberString ( manaStoneCurrentMana ) . c_str ( ) , pTarget - > GetName ( ) . c_str ( ) ) , LTT_DEFAULT ) ;
2018-07-31 12:45:14 +01:00
}
}
if ( manaStoneDestroyChance > = 1.0 | | Random : : RollDice ( 0.0 , 1.0 ) < = manaStoneDestroyChance )
{
player - > SendText ( csprintf ( " The %s is destroyed. " , GetName ( ) . c_str ( ) ) , LTT_DEFAULT ) ;
Remove ( ) ;
RecalculateEncumbrance ( ) ;
}
else
{
m_Qualities . SetInt ( ITEM_CUR_MANA_INT , 0 ) ;
2019-10-27 17:56:36 +00:00
NotifyIntStatUpdated ( ITEM_CUR_MANA_INT , false ) ;
2018-07-31 12:45:14 +01:00
m_Qualities . SetInt ( UI_EFFECTS_INT , 0 ) ;
NotifyIntStatUpdated ( UI_EFFECTS_INT , false ) ;
}
}
return WERROR_NONE ;
2018-04-25 19:28:00 -07:00
}
2018-07-31 12:45:14 +01:00
2018-04-25 19:28:00 -07:00
void CManaStoneUseEvent : : OnReadyToUse ( )
{
2018-07-12 14:41:21 -07:00
CWeenieObject * target = GetTarget ( ) ;
2018-04-25 19:28:00 -07:00
if ( ! target & & _target_id )
{
Cancel ( WERROR_OBJECT_GONE ) ;
return ;
}
2018-07-12 14:41:21 -07:00
CWeenieObject * tool = GetTool ( ) ;
2018-04-25 19:28:00 -07:00
if ( ! tool & & _tool_id )
{
Cancel ( WERROR_OBJECT_GONE ) ;
return ;
}
int error = WERROR_NONE ;
if ( target )
{
2018-07-12 14:41:21 -07:00
error = tool - > DoUseWithResponse ( _weenie , target ) ;
2018-04-25 19:28:00 -07:00
}
Done ( error ) ;
}