Added the ability for items to be activated upon cast instead of on completion of cast. These item effects also get interrupted by any movement.
This commit is contained in:
parent
fd96b23110
commit
852bbbc5a0
@ -66,6 +66,8 @@ struct Ability{
|
||||
bool canCancelCast=false;
|
||||
InputGroup*input;
|
||||
std::string icon;
|
||||
//If set to true, this ability instead activates immediately when a cast occurs. When the cast finishes, nothing happens instead.
|
||||
bool actionPerformedDuringCast=false;
|
||||
bool waitForRelease=false;
|
||||
//Ability action function, returns true if the ability can be casted, otherwise returns false.
|
||||
// Argument 1: Player* - player pointer
|
||||
|
||||
@ -43,6 +43,7 @@ enum BuffType{
|
||||
SLOWDOWN,
|
||||
BLOCK_SLOWDOWN,
|
||||
RESTORATION,
|
||||
RESTORATION_DURING_CAST,
|
||||
};
|
||||
|
||||
class Crawler;
|
||||
|
||||
@ -2236,6 +2236,7 @@ void Crawler::SetLoadoutItem(int slot,std::string itemName){
|
||||
}break;
|
||||
}
|
||||
Ability itemAbility{itemName,"","","Item.Item Cooldown Time"_F,0,inputGroup,"items/"+itemName+".png",VERY_DARK_RED,DARK_RED,PrecastData{GetLoadoutItem(slot).lock()->CastTime(),0,0},true};
|
||||
itemAbility.actionPerformedDuringCast=GetLoadoutItem(slot).lock()->UseDuringCast();
|
||||
|
||||
switch(slot){
|
||||
case 0:{
|
||||
|
||||
@ -105,6 +105,7 @@ void ItemInfo::InitializeItems(){
|
||||
std::vector<ItemAttribute>statValueList;
|
||||
uint32_t sellValue=0;
|
||||
uint32_t buyValue=0;
|
||||
bool useDuringCast=false;
|
||||
for(auto&[itemKey,itemValue]:data[key].GetKeys()){
|
||||
std::string keyName=itemKey;
|
||||
if(keyName=="Description"){
|
||||
@ -159,6 +160,9 @@ void ItemInfo::InitializeItems(){
|
||||
it.enhancement=enhancementStats;
|
||||
}
|
||||
if(scriptName!=""){
|
||||
if(scriptName=="RestoreDuringCast"){
|
||||
useDuringCast=true;
|
||||
}
|
||||
if(!ITEM_SCRIPTS.count(scriptName)){
|
||||
ERR("Could not load script "<<scriptName<<" for Item "<<key<<"!")
|
||||
}
|
||||
@ -173,6 +177,7 @@ void ItemInfo::InitializeItems(){
|
||||
it.set=setName;
|
||||
it.buyValue=buyValue;
|
||||
it.sellValue=sellValue;
|
||||
it.useDuringCast=useDuringCast;
|
||||
if(slot.size()>0){
|
||||
for(std::string&s:slot){
|
||||
if(!nameToEquipSlot.count(s))ERR("WARNING! Tried to add item "<<it.name<<" to slot "<<s<<" which doesn't exist!");
|
||||
@ -233,31 +238,53 @@ const uint32_t ItemProps::PropCount(const std::string&prop)const{
|
||||
void ItemInfo::InitializeScripts(){
|
||||
|
||||
ITEM_SCRIPTS["Restore"]=[](Crawler*game,ItemProps props){
|
||||
auto ParseItemScriptData=[&](const std::string&propName,std::function<void(Crawler*,int)>action,BuffType type){
|
||||
auto ParseItemScriptData=[&](const std::string&propName,std::function<void(Crawler*,int)>action){
|
||||
int restoreAmt=props.GetIntProp(propName);
|
||||
action(game,restoreAmt);
|
||||
if(restoreAmt>0&&props.PropCount(propName)==3){
|
||||
game->GetPlayer()->AddBuff(type,props.GetFloatProp(propName,2),restoreAmt,props.GetFloatProp(propName,1),action);
|
||||
game->GetPlayer()->AddBuff(RESTORATION,props.GetFloatProp(propName,2),restoreAmt,props.GetFloatProp(propName,1),action);
|
||||
}
|
||||
};
|
||||
ParseItemScriptData("HP Restore",[&](Crawler*game,int restoreAmt){
|
||||
game->GetPlayer()->Heal(restoreAmt);
|
||||
},RESTORATION);
|
||||
});
|
||||
ParseItemScriptData("HP % Restore",[&](Crawler*game,int restoreAmt){
|
||||
game->GetPlayer()->Heal(int(game->GetPlayer()->GetMaxHealth()*restoreAmt/100.0f));
|
||||
},RESTORATION);
|
||||
});
|
||||
ParseItemScriptData("MP Restore",[&](Crawler*game,int restoreAmt){
|
||||
game->GetPlayer()->RestoreMana(restoreAmt);
|
||||
},RESTORATION);
|
||||
});
|
||||
ParseItemScriptData("MP % Restore",[&](Crawler*game,int restoreAmt){
|
||||
game->GetPlayer()->RestoreMana(int(game->GetPlayer()->GetMaxMana()*props.GetIntProp("MP % Restore")/100.f));
|
||||
},RESTORATION);
|
||||
});
|
||||
return true;
|
||||
};
|
||||
ITEM_SCRIPTS["Buff"]=[](Crawler*game,ItemProps props){
|
||||
game->GetPlayer()->AddBuff(BuffType::ATTACK_PCT_UP,props.GetFloatProp("Attack %",1),props.GetFloatProp("Attack %",0)/100);
|
||||
return true;
|
||||
};
|
||||
ITEM_SCRIPTS["RestoreDuringCast"]=[&](Crawler*game,ItemProps props){
|
||||
auto ParseItemScriptData=[&](const std::string&propName,std::function<void(Crawler*,int)>action){
|
||||
int restoreAmt=props.GetIntProp(propName);
|
||||
action(game,restoreAmt);
|
||||
if(restoreAmt>0&&props.PropCount(propName)==3){
|
||||
game->GetPlayer()->AddBuff(RESTORATION_DURING_CAST,props.GetFloatProp(propName,2),restoreAmt,props.GetFloatProp(propName,1),action);
|
||||
}
|
||||
};
|
||||
ParseItemScriptData("HP Restore",[&](Crawler*game,int restoreAmt){
|
||||
game->GetPlayer()->Heal(restoreAmt);
|
||||
});
|
||||
ParseItemScriptData("HP % Restore",[&](Crawler*game,int restoreAmt){
|
||||
game->GetPlayer()->Heal(int(game->GetPlayer()->GetMaxHealth()*restoreAmt/100.0f));
|
||||
});
|
||||
ParseItemScriptData("MP Restore",[&](Crawler*game,int restoreAmt){
|
||||
game->GetPlayer()->RestoreMana(restoreAmt);
|
||||
});
|
||||
ParseItemScriptData("MP % Restore",[&](Crawler*game,int restoreAmt){
|
||||
game->GetPlayer()->RestoreMana(int(game->GetPlayer()->GetMaxMana()*props.GetIntProp("MP % Restore")/100.f));
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
ITEM_SCRIPTS.SetInitialized();
|
||||
std::cout<<ITEM_SCRIPTS.size()<<" item scripts have been loaded."<<std::endl;
|
||||
@ -748,4 +775,12 @@ bool Item::IsBlank(std::weak_ptr<Item>item){
|
||||
const bool Item::_IsBlank()const{
|
||||
Item::IsBlankStaticCallCounter++;
|
||||
return IsBlank();
|
||||
};
|
||||
};
|
||||
|
||||
const bool Item::UseDuringCast()const{
|
||||
return it->UseDuringCast();
|
||||
}
|
||||
|
||||
const bool ItemInfo::UseDuringCast()const{
|
||||
return useDuringCast;
|
||||
}
|
||||
@ -155,6 +155,7 @@ public:
|
||||
const Stats GetStats()const;
|
||||
const ItemScript&OnUseAction()const;
|
||||
const float CastTime()const;
|
||||
const bool UseDuringCast()const; //When true, the item is activated during the cast instead of after the cast.
|
||||
const float CooldownTime()const;
|
||||
//Use ISBLANK macro instead!! This should not be called directly!!
|
||||
const bool IsBlank()const;
|
||||
@ -247,6 +248,8 @@ class ItemInfo{
|
||||
ItemProps customProps;
|
||||
uint32_t buyValue=0;
|
||||
uint32_t sellValue=0;
|
||||
//If true, this item's action is activated at the beginning of the cast instead of after the cast completes.
|
||||
bool useDuringCast=false;
|
||||
private:
|
||||
static void InitializeScripts();
|
||||
static void InitializeSets();
|
||||
@ -272,6 +275,7 @@ public:
|
||||
const uint32_t GetSellValue()const;
|
||||
const bool CanBeSold()const;
|
||||
const bool CanBePurchased()const;
|
||||
const bool UseDuringCast()const;
|
||||
};
|
||||
|
||||
class ItemOverlay{
|
||||
|
||||
@ -438,9 +438,13 @@ void Player::Update(float fElapsedTime){
|
||||
if(CanAct(ability)){
|
||||
if(ability.cooldown==0&&GetMana()>=ability.manaCost){
|
||||
if(key.Held()||key.Released()&&&ability==castPrepAbility&&GetState()==State::PREP_CAST){
|
||||
if(AllowedToCast(ability)&&ability.action(this,{})){
|
||||
ability.cooldown=ability.COOLDOWN_TIME;
|
||||
ConsumeMana(ability.manaCost);
|
||||
if(AllowedToCast(ability)){
|
||||
bool allowed=ability.actionPerformedDuringCast;
|
||||
if(!allowed&&ability.action(this,{}))allowed=true;
|
||||
if(allowed){
|
||||
ability.cooldown=ability.COOLDOWN_TIME;
|
||||
ConsumeMana(ability.manaCost);
|
||||
}
|
||||
}else
|
||||
if(ability.precastInfo.precastTargetingRequired&&GetState()==State::NORMAL){
|
||||
PrepareCast(ability);
|
||||
@ -655,6 +659,7 @@ void Player::Moved(){
|
||||
state=State::NORMAL;
|
||||
castPrepAbility->waitForRelease=true;
|
||||
castInfo={"",0};
|
||||
std::erase_if(buffList,[](Buff&b){return b.type==RESTORATION_DURING_CAST;}); //Remove all buffs that would be applied during a cast, as we got interrupted.
|
||||
DAMAGENUMBER_LIST.push_back(std::make_shared<DamageNumber>(GetPos(),0,true,INTERRUPT));
|
||||
}
|
||||
for(MonsterSpawner&spawner:SPAWNER_LIST){
|
||||
@ -748,6 +753,7 @@ void Player::CastSpell(Ability&ability){
|
||||
castPosition=GetPos()+pointToCursor;
|
||||
}
|
||||
castInfo={ability.name,ability.precastInfo.castTime,ability.precastInfo.castTime,castPosition};
|
||||
if(ability.actionPerformedDuringCast){ability.action(this,castPosition);}
|
||||
SetState(State::CASTING);
|
||||
}
|
||||
|
||||
|
||||
@ -39,7 +39,7 @@ All rights reserved.
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 2
|
||||
#define VERSION_PATCH 1
|
||||
#define VERSION_BUILD 4530
|
||||
#define VERSION_BUILD 4534
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
||||
@ -53,9 +53,9 @@ ItemDatabase
|
||||
}
|
||||
Bandages
|
||||
{
|
||||
ItemScript = Restore
|
||||
ItemScript = RestoreDuringCast
|
||||
Description = Restores 30% health points over 6 seconds. The effect can be interrupted.
|
||||
HP % Restore = 30%
|
||||
HP % Restore = 5%,1,6
|
||||
Cast Time = 6.0
|
||||
Cooldown Time = 5.0
|
||||
ItemCategory = Consumables
|
||||
|
||||
@ -22,4 +22,13 @@ ItemScript
|
||||
{
|
||||
Attack % = 0,0.0
|
||||
}
|
||||
|
||||
# Unlike an item or ability that requires a cast to perform, this applies a buff immediately and then moving cancels the buff mid-application.
|
||||
RestoreDuringCast
|
||||
{
|
||||
HP Restore = 0,0.0,0.0
|
||||
HP % Restore = 0,0.0,0.0
|
||||
MP Restore = 0,0.0,0.0
|
||||
MP % Restore = 0,0.0,0.0
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user