Implemented Poisonous Arrow enchant. Release Build 10810.
This commit is contained in:
parent
8ac625660d
commit
150a72db73
@ -1127,6 +1127,13 @@ void AiL::RenderWorld(float fElapsedTime){
|
|||||||
if(player->GetState()==State::BLOCK){
|
if(player->GetState()==State::BLOCK){
|
||||||
view.DrawDecal(player->GetPos()+vf2d{0,-player->GetZ()*(std::signbit(scale.y)?-1:1)}-vf2d{12,12},GFX["block.png"].Decal());
|
view.DrawDecal(player->GetPos()+vf2d{0,-player->GetZ()*(std::signbit(scale.y)?-1:1)}-vf2d{12,12},GFX["block.png"].Decal());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(player->IsPoisonArrowAutoAttackReady()&&player->poisonArrowLastParticleTimer==0.f){
|
||||||
|
const float particleSize{fmod(game->GetRunTime(),0.4f)<0.2f?1.f:1.5f};
|
||||||
|
game->AddEffect(std::make_unique<Effect>(player->GetPos()-vf2d{0,4.f}-player->GetFacingDirVector()*6.f,0.2f,"energy_particle.png",player->OnUpperLevel(),vf2d{particleSize,particleSize}*1.2f,0.05f,vf2d{},Pixel{0,255,255,120},util::random(2*PI),0.f,true));
|
||||||
|
game->AddEffect(std::make_unique<Effect>(player->GetPos()-vf2d{0,4.f}-player->GetFacingDirVector()*6.f,0.2f,"energy_particle.png",player->OnUpperLevel(),vf2d{particleSize,particleSize},0.05f,vf2d{},DARK_GREEN,util::random(2*PI)));
|
||||||
|
player->poisonArrowLastParticleTimer=0.15f;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
auto RenderZone=[&](geom2d::rect<int>&zone){
|
auto RenderZone=[&](geom2d::rect<int>&zone){
|
||||||
|
@ -63,9 +63,11 @@ All rights reserved.
|
|||||||
class SteamKeyboardCallbackHandler;
|
class SteamKeyboardCallbackHandler;
|
||||||
class SteamStatsReceivedHandler;
|
class SteamStatsReceivedHandler;
|
||||||
|
|
||||||
#define CreateBullet(type) INCLUDE_BULLET_LIST \
|
INCLUDE_BULLET_LIST
|
||||||
BULLET_LIST.push_back(std::make_unique<type>(type
|
|
||||||
#define EndBullet ));
|
#define CreateBullet(type) \
|
||||||
|
*(type*const)(BULLET_LIST.emplace_back(std::make_unique<type>(type
|
||||||
|
#define EndBullet )).get())
|
||||||
|
|
||||||
using HurtReturnValue=bool;
|
using HurtReturnValue=bool;
|
||||||
using HurtList=std::vector<std::pair<std::variant<Monster*,Player*>,HurtReturnValue>>;
|
using HurtList=std::vector<std::pair<std::variant<Monster*,Player*>,HurtReturnValue>>;
|
||||||
|
@ -43,6 +43,7 @@ All rights reserved.
|
|||||||
#include "olcUTIL_Geometry2D.h"
|
#include "olcUTIL_Geometry2D.h"
|
||||||
|
|
||||||
INCLUDE_game
|
INCLUDE_game
|
||||||
|
INCLUDE_GFX
|
||||||
|
|
||||||
Arrow::Arrow(vf2d pos,vf2d targetPos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly,Pixel col)
|
Arrow::Arrow(vf2d pos,vf2d targetPos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly,Pixel col)
|
||||||
:finalDistance(geom2d::line(pos,targetPos).length()*1.2f),acc(PI/2*250),targetPos(targetPos),
|
:finalDistance(geom2d::line(pos,targetPos).length()*1.2f),acc(PI/2*250),targetPos(targetPos),
|
||||||
@ -94,6 +95,7 @@ BulletDestroyState Arrow::PlayerHit(Player*player)
|
|||||||
{
|
{
|
||||||
fadeOutTime=0.2f;
|
fadeOutTime=0.2f;
|
||||||
game->AddEffect(std::make_unique<Effect>(player->GetPos(),0,"splash_effect.png",upperLevel,player->GetSizeMult(),0.25));
|
game->AddEffect(std::make_unique<Effect>(player->GetPos(),0,"splash_effect.png",upperLevel,player->GetSizeMult(),0.25));
|
||||||
|
if(poisonArrow)player->AddBuff(BuffRestorationType::OVER_TIME,BuffOverTimeType::HP_DAMAGE_OVER_TIME,"Poisonous Arrow"_ENC["POISON DURATION"],damage*("Poisonous Arrow"_ENC["POISON TICK DAMAGE"]/100.f),1.f);
|
||||||
return BulletDestroyState::KEEP_ALIVE;
|
return BulletDestroyState::KEEP_ALIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,9 +103,21 @@ BulletDestroyState Arrow::MonsterHit(Monster&monster,const uint8_t markStacksBef
|
|||||||
{
|
{
|
||||||
fadeOutTime=0.2f;
|
fadeOutTime=0.2f;
|
||||||
game->AddEffect(std::make_unique<Effect>(monster.GetPos(),0,"splash_effect.png",upperLevel,monster.GetSizeMult(),0.25));
|
game->AddEffect(std::make_unique<Effect>(monster.GetPos(),0,"splash_effect.png",upperLevel,monster.GetSizeMult(),0.25));
|
||||||
|
if(poisonArrow)monster.AddBuff(BuffRestorationType::OVER_TIME,BuffOverTimeType::HP_DAMAGE_OVER_TIME,"Poisonous Arrow"_ENC["POISON DURATION"],damage*("Poisonous Arrow"_ENC["POISON TICK DAMAGE"]/100.f),1.f);
|
||||||
return BulletDestroyState::KEEP_ALIVE;
|
return BulletDestroyState::KEEP_ALIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Arrow::ModifyOutgoingDamageData(HurtDamageInfo&data){
|
void Arrow::ModifyOutgoingDamageData(HurtDamageInfo&data){
|
||||||
if(friendly)data.hurtFlags|=HurtFlag::PLAYER_ABILITY;
|
if(friendly)data.hurtFlags|=HurtFlag::PLAYER_ABILITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Arrow::Draw(const Pixel blendCol)const{
|
||||||
|
if(poisonArrow){
|
||||||
|
game->SetDecalMode(DecalMode::ADDITIVE);
|
||||||
|
game->view.DrawRotatedDecal(pos,GFX["glow.png"].Decal(),image_angle,GFX["glow.png"].Sprite()->Size()/2,scale,{255,255,0,120});
|
||||||
|
game->SetDecalMode(DecalMode::NORMAL);
|
||||||
|
Bullet::Draw({128,192,0,blendCol.a});
|
||||||
|
}else{
|
||||||
|
Bullet::Draw(blendCol);
|
||||||
|
}
|
||||||
|
}
|
@ -72,6 +72,7 @@ struct Arrow:public Bullet{
|
|||||||
float finalDistance=0;
|
float finalDistance=0;
|
||||||
float acc=PI/2*250;
|
float acc=PI/2*250;
|
||||||
vf2d targetPos;
|
vf2d targetPos;
|
||||||
|
bool poisonArrow{false};
|
||||||
Arrow(vf2d pos,vf2d targetPos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly=false,Pixel col=WHITE);
|
Arrow(vf2d pos,vf2d targetPos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly=false,Pixel col=WHITE);
|
||||||
Arrow(vf2d pos,vf2d targetPos,vf2d vel,const std::string_view gfx,float radius,int damage,bool upperLevel,bool friendly=false,Pixel col=WHITE);
|
Arrow(vf2d pos,vf2d targetPos,vf2d vel,const std::string_view gfx,float radius,int damage,bool upperLevel,bool friendly=false,Pixel col=WHITE);
|
||||||
void Update(float fElapsedTime)override;
|
void Update(float fElapsedTime)override;
|
||||||
@ -81,6 +82,7 @@ struct Arrow:public Bullet{
|
|||||||
BulletDestroyState PlayerHit(Player*player)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _PlayerHit()!!
|
BulletDestroyState PlayerHit(Player*player)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _PlayerHit()!!
|
||||||
BulletDestroyState MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!!
|
BulletDestroyState MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!!
|
||||||
void ModifyOutgoingDamageData(HurtDamageInfo&data);
|
void ModifyOutgoingDamageData(HurtDamageInfo&data);
|
||||||
|
void Draw(const Pixel blendCol)const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ChargedArrow:public Bullet{
|
struct ChargedArrow:public Bullet{
|
||||||
|
@ -348,6 +348,8 @@ void Player::Update(float fElapsedTime){
|
|||||||
lastDotTimer=std::max(0.f,lastDotTimer-fElapsedTime);
|
lastDotTimer=std::max(0.f,lastDotTimer-fElapsedTime);
|
||||||
lastPathfindingCooldown=std::max(0.f,lastPathfindingCooldown-fElapsedTime);
|
lastPathfindingCooldown=std::max(0.f,lastPathfindingCooldown-fElapsedTime);
|
||||||
lowHealthSoundPlayedTimer=std::max(0.f,lowHealthSoundPlayedTimer-fElapsedTime);
|
lowHealthSoundPlayedTimer=std::max(0.f,lowHealthSoundPlayedTimer-fElapsedTime);
|
||||||
|
poisonArrowReadyTimer=std::max(0.f,poisonArrowReadyTimer-fElapsedTime);
|
||||||
|
poisonArrowLastParticleTimer=std::max(0.f,poisonArrowLastParticleTimer-fElapsedTime);
|
||||||
if(hurtRumbleTime>0.f){
|
if(hurtRumbleTime>0.f){
|
||||||
hurtRumbleTime=std::max(0.f,hurtRumbleTime-fElapsedTime);
|
hurtRumbleTime=std::max(0.f,hurtRumbleTime-fElapsedTime);
|
||||||
if(hurtRumbleTime==0.f){
|
if(hurtRumbleTime==0.f){
|
||||||
@ -983,7 +985,7 @@ void Player::SetFacingDirection(Key direction){
|
|||||||
facingDirection=direction;
|
facingDirection=direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
Key Player::GetFacingDirection(){
|
Key Player::GetFacingDirection()const{
|
||||||
return facingDirection;
|
return facingDirection;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1959,3 +1961,28 @@ void Player::ReduceAutoAttackTimer(const float reduceAmt){
|
|||||||
const float&Player::GetAutoAttackTimer()const{
|
const float&Player::GetAutoAttackTimer()const{
|
||||||
return attack_cooldown_timer;
|
return attack_cooldown_timer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool Player::IsPoisonArrowAutoAttackReady()const{
|
||||||
|
return HasEnchant("Poisonous Arrow")&&poisonArrowReadyTimer==0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
const vf2d Player::GetFacingDirVector()const{
|
||||||
|
switch(GetFacingDirection()){
|
||||||
|
case UP:{
|
||||||
|
return {0,-1};
|
||||||
|
}break;
|
||||||
|
case DOWN:{
|
||||||
|
return {0,1};
|
||||||
|
}break;
|
||||||
|
case LEFT:{
|
||||||
|
return {-1,0};
|
||||||
|
}break;
|
||||||
|
case RIGHT:{
|
||||||
|
return {1,0};
|
||||||
|
}break;
|
||||||
|
default:{
|
||||||
|
ERR(std::format("WARNING! Somehow got an invalid facing direction: {}. THIS SHOULD NOT BE HAPPENING!",int(GetFacingDirection())));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -144,7 +144,7 @@ public:
|
|||||||
float GetAttackRangeMult();
|
float GetAttackRangeMult();
|
||||||
float GetSpinAngle();
|
float GetSpinAngle();
|
||||||
State::State GetState();
|
State::State GetState();
|
||||||
Key GetFacingDirection();
|
Key GetFacingDirection()const;
|
||||||
vf2d GetVelocity();
|
vf2d GetVelocity();
|
||||||
bool HasIframes();
|
bool HasIframes();
|
||||||
void Update(float fElapsedTime);
|
void Update(float fElapsedTime);
|
||||||
@ -305,6 +305,7 @@ public:
|
|||||||
void CheckAndPerformAbility(Ability&ability,InputGroup key);
|
void CheckAndPerformAbility(Ability&ability,InputGroup key);
|
||||||
void ReduceAutoAttackTimer(const float reduceAmt);
|
void ReduceAutoAttackTimer(const float reduceAmt);
|
||||||
const float&GetAutoAttackTimer()const;
|
const float&GetAutoAttackTimer()const;
|
||||||
|
const vf2d GetFacingDirVector()const; //Returns a normalized vector based on the facing direction of the character. Ex. {0,-1} for north and {1,0} for east.
|
||||||
private:
|
private:
|
||||||
int hp="Warrior.BaseHealth"_I;
|
int hp="Warrior.BaseHealth"_I;
|
||||||
int mana="Player.BaseMana"_I;
|
int mana="Player.BaseMana"_I;
|
||||||
@ -384,6 +385,8 @@ private:
|
|||||||
std::unordered_set<std::string>enchantList;
|
std::unordered_set<std::string>enchantList;
|
||||||
void OnAbilityUse(const Ability&ability); //Callback when an ability successfully is used and has gone on cooldown.
|
void OnAbilityUse(const Ability&ability); //Callback when an ability successfully is used and has gone on cooldown.
|
||||||
const bool LastReserveEnchantConditionsMet()const;
|
const bool LastReserveEnchantConditionsMet()const;
|
||||||
|
const bool IsPoisonArrowAutoAttackReady()const; //NOTE: Also checks to make sure we have the enchant built-in...
|
||||||
|
float poisonArrowLastParticleTimer{};
|
||||||
protected:
|
protected:
|
||||||
const float ATTACK_COOLDOWN="Warrior.Auto Attack.Cooldown"_F;
|
const float ATTACK_COOLDOWN="Warrior.Auto Attack.Cooldown"_F;
|
||||||
const float MAGIC_ATTACK_COOLDOWN="Wizard.Auto Attack.Cooldown"_F;
|
const float MAGIC_ATTACK_COOLDOWN="Wizard.Auto Attack.Cooldown"_F;
|
||||||
@ -436,6 +439,7 @@ protected:
|
|||||||
float leapTimer{};
|
float leapTimer{};
|
||||||
float totalLeapTime{};
|
float totalLeapTime{};
|
||||||
vf2d leapStartingPos{};
|
vf2d leapStartingPos{};
|
||||||
|
float poisonArrowReadyTimer{};
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma region Warrior
|
#pragma region Warrior
|
||||||
|
@ -71,7 +71,11 @@ bool Ranger::AutoAttack(){
|
|||||||
vf2d extendedLine=pointTowardsCursor.upoint(1.1f);
|
vf2d extendedLine=pointTowardsCursor.upoint(1.1f);
|
||||||
float angleToCursor=atan2(extendedLine.y-GetPos().y,extendedLine.x-GetPos().x);
|
float angleToCursor=atan2(extendedLine.y-GetPos().y,extendedLine.x-GetPos().x);
|
||||||
attack_cooldown_timer=ARROW_ATTACK_COOLDOWN-GetAttackRecoveryRateReduction();
|
attack_cooldown_timer=ARROW_ATTACK_COOLDOWN-GetAttackRecoveryRateReduction();
|
||||||
CreateBullet(Arrow)(GetPos(),extendedLine,vf2d{cos(angleToCursor)*"Ranger.Auto Attack.ArrowSpd"_F,float(sin(angleToCursor)*"Ranger.Auto Attack.ArrowSpd"_F-PI/8*"Ranger.Auto Attack.ArrowSpd"_F)}+movementVelocity/1.5f,"Ranger.Auto Attack.Radius"_F,int(GetAttack()*"Ranger.Auto Attack.DamageMult"_F),OnUpperLevel(),true)EndBullet;
|
Arrow&arrow{CreateBullet(Arrow)(GetPos(),extendedLine,vf2d{cos(angleToCursor)*"Ranger.Auto Attack.ArrowSpd"_F,float(sin(angleToCursor)*"Ranger.Auto Attack.ArrowSpd"_F-PI/8*"Ranger.Auto Attack.ArrowSpd"_F)}+movementVelocity/1.5f,"Ranger.Auto Attack.Radius"_F,int(GetAttack()*"Ranger.Auto Attack.DamageMult"_F),OnUpperLevel(),true)EndBullet};
|
||||||
|
if(IsPoisonArrowAutoAttackReady()){
|
||||||
|
arrow.poisonArrow=true;
|
||||||
|
poisonArrowReadyTimer="Poisonous Arrow"_ENC["POISON ARROW RESET FREQUENCY"];
|
||||||
|
}
|
||||||
BULLET_LIST.back()->SetIsPlayerAutoAttackProjectile();
|
BULLET_LIST.back()->SetIsPlayerAutoAttackProjectile();
|
||||||
SetState(State::SHOOT_ARROW);
|
SetState(State::SHOOT_ARROW);
|
||||||
SetAnimationBasedOnTargetingDirection("SHOOT",angleToCursor);
|
SetAnimationBasedOnTargetingDirection("SHOOT",angleToCursor);
|
||||||
|
@ -39,7 +39,7 @@ All rights reserved.
|
|||||||
#define VERSION_MAJOR 1
|
#define VERSION_MAJOR 1
|
||||||
#define VERSION_MINOR 2
|
#define VERSION_MINOR 2
|
||||||
#define VERSION_PATCH 3
|
#define VERSION_PATCH 3
|
||||||
#define VERSION_BUILD 10803
|
#define VERSION_BUILD 10810
|
||||||
|
|
||||||
#define stringify(a) stringify_(a)
|
#define stringify(a) stringify_(a)
|
||||||
#define stringify_(a) #a
|
#define stringify_(a) #a
|
||||||
|
@ -121,6 +121,7 @@ Images
|
|||||||
GFX_Fragment = items/Fragment.png
|
GFX_Fragment = items/Fragment.png
|
||||||
GFX_MonsterSoul = monstersoul.png
|
GFX_MonsterSoul = monstersoul.png
|
||||||
GFX_MonsterSoulGlow = monstersoulglow.png
|
GFX_MonsterSoulGlow = monstersoulglow.png
|
||||||
|
GFX_Glow = glow.png
|
||||||
|
|
||||||
GFX_Thief_Sheet = nico-thief.png
|
GFX_Thief_Sheet = nico-thief.png
|
||||||
GFX_Trapper_Sheet = nico-trapper.png
|
GFX_Trapper_Sheet = nico-trapper.png
|
||||||
|
Binary file not shown.
BIN
Adventures in Lestoria/assets/glow.png
Normal file
BIN
Adventures in Lestoria/assets/glow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1017 B |
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user