ThunderOrb emits lightning towards target when nearby. Release Build 13059.
Some checks failed
Emscripten Build / Build_and_Deploy_Web_Build (push) Failing after 13h19m47s
Some checks failed
Emscripten Build / Build_and_Deploy_Web_Build (push) Failing after 13h19m47s
This commit is contained in:
parent
9f1e701537
commit
d94440bdcb
@ -78,6 +78,7 @@ INCLUDE_BULLET_LIST
|
||||
|
||||
using HurtReturnValue=bool;
|
||||
using HurtListItem=std::pair<std::variant<Monster*,Player*>,HurtReturnValue>;
|
||||
|
||||
using HurtList=std::vector<HurtListItem>;
|
||||
using StackCount=uint8_t;
|
||||
using MarkTime=float;
|
||||
|
||||
@ -463,6 +463,7 @@ private:
|
||||
LightningBoltEmitter lightning;
|
||||
ThunderOrbSettings settings;
|
||||
float damageTickTimer{};
|
||||
float lightningTickTimer{};
|
||||
};
|
||||
|
||||
struct GhostSaber:public Bullet{
|
||||
|
||||
@ -37,6 +37,7 @@ All rights reserved.
|
||||
#pragma endregion
|
||||
#include "Emitter.h"
|
||||
#include <memory>
|
||||
#include<ranges>
|
||||
|
||||
std::vector<std::unique_ptr<IEmitter>>EMITTER_LIST;
|
||||
|
||||
@ -47,7 +48,7 @@ bool IEmitter::Update(float fElapsedTime){
|
||||
lastEmit=std::max(lastEmit-fElapsedTime,0.f);
|
||||
if(lastEmit==0){
|
||||
lastEmit=frequency;
|
||||
Emit();
|
||||
for(int i:std::ranges::iota_view(0,amountToEmit))Emit();
|
||||
}
|
||||
lifetime-=fElapsedTime;
|
||||
if(lifetime<0){
|
||||
|
||||
@ -37,6 +37,8 @@ All rights reserved.
|
||||
#pragma endregion
|
||||
#pragma once
|
||||
#include "olcUTIL_Geometry2D.h"
|
||||
#include<memory>
|
||||
#include"FriendlyType.h"
|
||||
|
||||
struct IEmitter{
|
||||
friend class AiL;
|
||||
@ -45,6 +47,8 @@ struct IEmitter{
|
||||
float lastEmit=0;
|
||||
private:
|
||||
bool dead=false;
|
||||
protected:
|
||||
int amountToEmit{1};
|
||||
public:
|
||||
virtual ~IEmitter()=default;
|
||||
IEmitter(float frequency,float timer);
|
||||
@ -52,15 +56,25 @@ public:
|
||||
virtual void Emit()=0;
|
||||
};
|
||||
|
||||
class Effect;
|
||||
|
||||
class LightningBoltEmitter:public IEmitter{
|
||||
vf2d startPos,endPos;
|
||||
bool upperLevel;
|
||||
void DrawLightningBolt();
|
||||
std::vector<std::weak_ptr<Effect>>activeLightningBolts;
|
||||
public:
|
||||
enum AimAtTarget:bool{
|
||||
AIMS_RANDOMLY=false,
|
||||
AIMS_AT_TARGET=true,
|
||||
};
|
||||
virtual ~LightningBoltEmitter()=default;
|
||||
LightningBoltEmitter(vf2d startPos,vf2d endPos,float frequency,float timer,bool upperLevel);
|
||||
void SetStartEndPos(vf2d startPos,vf2d endPos);
|
||||
LightningBoltEmitter(vf2d startPos,vf2d endPos,float frequency,float timer,bool upperLevel,int lightningBoltsToEmit,AimAtTarget aimsAtTargets=AIMS_RANDOMLY,FriendlyType friendly=NON_FRIENDLY,float lightningFadeOutSpd=0.2f);
|
||||
void SetStartEndPos(vf2d startPos,vf2d endPos);
|
||||
void Emit()override;
|
||||
void ChangeActiveLightningTarget(vf2d newPos);
|
||||
void DrawLightningBolt(const vf2d targetPos);
|
||||
bool drawLightningBoltsInBack{false};
|
||||
private:
|
||||
vf2d startPos,endPos;
|
||||
bool upperLevel;
|
||||
float lightningFadeOutSpd;
|
||||
AimAtTarget aimsAtTargets{AIMS_RANDOMLY};
|
||||
FriendlyType friendly{NON_FRIENDLY};
|
||||
};
|
||||
@ -109,4 +109,13 @@ const float Entity::GetMoveSpdMult()const{
|
||||
|
||||
const int Entity::GetAttack()const{
|
||||
CallClassFunc(GetAttack());
|
||||
}
|
||||
|
||||
const FriendlyType Entity::IsFriendly()const{
|
||||
if(is(Player*))return FRIENDLY;
|
||||
return NON_FRIENDLY;
|
||||
}
|
||||
|
||||
const float Entity::GetSizeMult()const{
|
||||
CallClassFunc(GetSizeMult());
|
||||
}
|
||||
@ -41,6 +41,7 @@ All rights reserved.
|
||||
#include <variant>
|
||||
#include"Buff.h"
|
||||
#include"HurtDamageInfo.h"
|
||||
#include"FriendlyType.h"
|
||||
|
||||
class Player;
|
||||
class Monster;
|
||||
@ -49,6 +50,7 @@ class Monster;
|
||||
class Entity{
|
||||
friend struct std::hash<Entity>;
|
||||
friend bool operator==(const Entity&lhs,const Entity&rhs);
|
||||
friend class AiL;
|
||||
public:
|
||||
Entity(Player*player);
|
||||
Entity(Monster*monster);
|
||||
@ -65,7 +67,9 @@ public:
|
||||
const std::vector<Buff>GetBuffs(BuffType buff)const;
|
||||
const bool OnUpperLevel()const;
|
||||
const float GetMoveSpdMult()const;
|
||||
const float GetSizeMult()const;
|
||||
const int GetAttack()const;
|
||||
const FriendlyType IsFriendly()const;
|
||||
private:
|
||||
const std::variant<Monster*,Player*>entity;
|
||||
inline bool operator==(const Entity&rhs){return entity==rhs.entity;}
|
||||
@ -81,4 +85,5 @@ struct std::hash<Entity>
|
||||
if(std::holds_alternative<Monster*>(entity.entity))return std::hash<intptr_t>()(intptr_t(std::get<Monster*>(entity.entity)));
|
||||
ERR("Entity is not a valid type! THIS SHOULD NOT BE HAPPENING!");
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -110,7 +110,7 @@ void LightningBolt::ApplyLightningShock(const Monster&monster,const bool onUpper
|
||||
int lightningChainDamage{int(game->GetPlayer()->GetAttack()*"Wizard.Ability 2.LightningChainDamageMult"_F)};
|
||||
if(chainLightningRepeatCount>0)lightningChainDamage=int(game->GetPlayer()->GetAttack()*"Chain Lightning"_ENC["SHOCK DAMAGE"]/100.f);
|
||||
if(m->Hurt(lightningChainDamage,onUpperLevel,0,HurtFlag::PLAYER_ABILITY)){
|
||||
EMITTER_LIST.emplace_back(std::make_unique<LightningBoltEmitter>(LightningBoltEmitter(monster.GetPos(),m->GetPos(),"Wizard.Ability 2.LightningChainFrequency"_F,"Wizard.Ability 2.LightningChainLifetime"_F,onUpperLevel)));
|
||||
EMITTER_LIST.emplace_back(std::make_unique<LightningBoltEmitter>(LightningBoltEmitter(monster.GetPos(),m->GetPos(),"Wizard.Ability 2.LightningChainFrequency"_F,"Wizard.Ability 2.LightningChainLifetime"_F,onUpperLevel,1)));
|
||||
game->AddEffect(Effect{m->GetPos(),"Wizard.Ability 2.LightningChainSplashLifetime"_F,"lightning_splash_effect.png",onUpperLevel,monster.GetSizeMult(),"Wizard.Ability 2.LightningChainSplashFadeoutTime"_F,vf2d{},WHITE,"Wizard.Ability 2.LightningChainSplashRotationRange"_FRange});
|
||||
int chainLightningRepeat{};
|
||||
if(chainLightningRepeatCount>0)chainLightningRepeat=chainLightningRepeatCount-1;
|
||||
|
||||
@ -35,48 +35,46 @@ Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
|
||||
All rights reserved.
|
||||
*/
|
||||
#pragma endregion
|
||||
#include "Emitter.h"
|
||||
#include "olcUTIL_Geometry2D.h"
|
||||
#include "util.h"
|
||||
#include "AdventuresInLestoria.h"
|
||||
#include "DEFINES.h"
|
||||
#include<memory>
|
||||
#include"Emitter.h"
|
||||
#include"olcUTIL_Geometry2D.h"
|
||||
#include"util.h"
|
||||
#include"AdventuresInLestoria.h"
|
||||
#include"DEFINES.h"
|
||||
|
||||
INCLUDE_game
|
||||
|
||||
LightningBoltEmitter::LightningBoltEmitter(vf2d startPos,vf2d endPos,float frequency,float lifetime,bool upperLevel)
|
||||
:startPos(startPos),endPos(endPos),IEmitter(frequency,lifetime),upperLevel(upperLevel){}
|
||||
LightningBoltEmitter::LightningBoltEmitter(vf2d startPos,vf2d endPos,float frequency,float lifetime,bool upperLevel,int lightningBoltsToEmit,AimAtTarget aimsAtTargets,FriendlyType friendly,float lightningFadeOutSpd)
|
||||
:startPos(startPos),endPos(endPos),IEmitter(frequency,lifetime),upperLevel(upperLevel),lightningFadeOutSpd(lightningFadeOutSpd),aimsAtTargets(aimsAtTargets),friendly(friendly){
|
||||
amountToEmit=lightningBoltsToEmit;
|
||||
}
|
||||
|
||||
|
||||
void LightningBoltEmitter::Emit(){
|
||||
std::erase_if(activeLightningBolts,[](const std::weak_ptr<Effect>&ptr){return ptr.expired();});
|
||||
DrawLightningBolt();
|
||||
if(aimsAtTargets){
|
||||
const std::vector<Entity>foundTargets{game->GetTargetsInRange(startPos,util::distance(endPos,startPos),upperLevel,0.f,friendly==FRIENDLY?HurtType::MONSTER:HurtType::PLAYER)};
|
||||
for(const Entity&ent:foundTargets)DrawLightningBolt(ent.GetPos());
|
||||
if(foundTargets.empty())DrawLightningBolt(endPos);
|
||||
}else DrawLightningBolt(endPos);
|
||||
}
|
||||
|
||||
void LightningBoltEmitter::ChangeActiveLightningTarget(vf2d newPos){
|
||||
for(std::weak_ptr<Effect>&activeLightningBolt:activeLightningBolts|std::views::filter([](std::weak_ptr<Effect>&ptr){return !ptr.expired();}){
|
||||
activeLightningBolt.lock();
|
||||
}
|
||||
}
|
||||
|
||||
void LightningBoltEmitter::DrawLightningBolt(){
|
||||
void LightningBoltEmitter::DrawLightningBolt(const vf2d targetPos){
|
||||
vf2d currentPos=startPos;
|
||||
const int MAX_ITERATIONS=100;
|
||||
geom2d::line<float>lineToTarget=geom2d::line<float>(startPos,endPos);
|
||||
geom2d::line<float>lineToTarget=geom2d::line<float>(startPos,targetPos);
|
||||
float targetAngle=atan2(lineToTarget.vector().y,lineToTarget.vector().x);
|
||||
float targetDist=lineToTarget.length()*util::random(0.5f);
|
||||
targetAngle+=util::random((PI/2))-PI/4;
|
||||
geom2d::line<float>lightningLine=geom2d::line<float>(currentPos,currentPos+vf2d{cos(targetAngle)*targetDist,sin(targetAngle)*targetDist});
|
||||
game->AddEffect(Effect{lightningLine.upoint(0),0,"chain_lightning.png",upperLevel,vf2d{lightningLine.length(),0.2f},0.2f,vf2d{},WHITE,targetAngle,0,true});
|
||||
game->AddEffect(Effect{lightningLine.upoint(0),0,"chain_lightning.png",upperLevel,vf2d{lightningLine.length(),0.2f},lightningFadeOutSpd,vf2d{},WHITE,targetAngle,0,true},drawLightningBoltsInBack);
|
||||
int iterations=1;
|
||||
currentPos+=vf2d{cos(targetAngle)*targetDist,sin(targetAngle)*targetDist};
|
||||
while(iterations<MAX_ITERATIONS&&geom2d::line<float>(currentPos,endPos).length()>1){
|
||||
geom2d::line<float>lineToTarget=geom2d::line<float>(currentPos,endPos);
|
||||
while(iterations<MAX_ITERATIONS&&geom2d::line<float>(currentPos,targetPos).length()>1){
|
||||
geom2d::line<float>lineToTarget=geom2d::line<float>(currentPos,targetPos);
|
||||
float targetAngle=atan2(lineToTarget.vector().y,lineToTarget.vector().x);
|
||||
float targetDist=lineToTarget.length()*util::random(0.5f);
|
||||
targetAngle+=util::random((PI/2))-PI/4;
|
||||
geom2d::line<float>lightningLine=geom2d::line<float>(currentPos,currentPos+vf2d{cos(targetAngle)*targetDist,sin(targetAngle)*targetDist});
|
||||
game->AddEffect(Effect{lightningLine.upoint(0),0,"chain_lightning.png",upperLevel,vf2d{lightningLine.length(),0.2f},0.2f,vf2d{},WHITE,targetAngle,0,true});
|
||||
game->AddEffect(Effect{lightningLine.upoint(0),0,"chain_lightning.png",upperLevel,vf2d{lightningLine.length(),0.2f},lightningFadeOutSpd,vf2d{},WHITE,targetAngle,0,true},drawLightningBoltsInBack);
|
||||
currentPos+=vf2d{cos(targetAngle)*targetDist,sin(targetAngle)*targetDist};
|
||||
iterations++;
|
||||
}
|
||||
|
||||
@ -43,6 +43,7 @@ INCLUDE_game
|
||||
|
||||
DEFINE_STRATEGY(SKELETON_MAGE)
|
||||
if(!m.currentCast){
|
||||
|
||||
m.RunStrategy(RUN_AWAY);
|
||||
}
|
||||
END_STRATEGY
|
||||
@ -40,25 +40,37 @@ All rights reserved.
|
||||
INCLUDE_game
|
||||
|
||||
ThunderOrb::ThunderOrb(const vf2d pos,const Entity target,const int monsterDamage,const ThunderOrbSettings settings,const float rotateTowardsSpeed,const bool upperLevel,const FriendlyType friendly,const Pixel col,const vf2d scale,const float image_angle)
|
||||
:settings(settings),damageTickTimer(settings.tickRate),lightning(pos,pos+vf2d{settings.range/100.f*24,util::random(2*PI)}.cart(),settings.lightningBoltTickRate,settings.lifetime,upperLevel),HomingBullet(pos,target,rotateTowardsSpeed,"thunderorb.png",settings.lifetime,100.f*target.GetMoveSpdMult()*settings.moveSpdPct,0.f,monsterDamage,upperLevel,friendly,col,scale,image_angle){}
|
||||
:settings(settings),damageTickTimer(settings.tickRate),lightning(pos,pos+vf2d{settings.range/100.f*24,util::random(2*PI)}.cart(),INFINITY,settings.lifetime,upperLevel,3,LightningBoltEmitter::AIMS_AT_TARGET,friendly,settings.lightningBoltTickRate),HomingBullet(pos,target,rotateTowardsSpeed,"thunderorb.png",settings.lifetime,100.f*target.GetMoveSpdMult()*settings.moveSpdPct,0.f,monsterDamage,upperLevel,friendly,col,scale,image_angle){
|
||||
lightning.drawLightningBoltsInBack=true;
|
||||
}
|
||||
void ThunderOrb::Update(float fElapsedTime){
|
||||
static vf2d lightningBoltRandomPos{};
|
||||
|
||||
lightningBoltRandomPos=pos+vf2d{settings.range/100.f*24,util::random(2*PI)}.cart();
|
||||
lightning.SetStartEndPos(pos,lightningBoltRandomPos);
|
||||
lightning.SetStartEndPos(pos,pos);
|
||||
|
||||
std::vector<Entity>foundTargets{game->GetTargetsInRange(pos,settings.range/100.f*24,upperLevel,0.f,friendly==FRIENDLY?HurtType::MONSTER:HurtType::PLAYER)};
|
||||
|
||||
if((damageTickTimer-=fElapsedTime)<=0.f){
|
||||
const HurtList&hurtTargets{game->Hurt(pos,settings.range/100.f*24,damage*settings.attackMult,OnUpperLevel(),GetZ(),friendly?HurtType::MONSTER:HurtType::PLAYER)};
|
||||
|
||||
std::ranges::for_each(hurtTargets,[&lightning=lightning,&pos=pos](const auto&pair){
|
||||
Entity target{pair.first};
|
||||
lightning.SetStartEndPos(pos,target.GetPos());
|
||||
lightning.Emit();
|
||||
});
|
||||
|
||||
for(Entity&ent:foundTargets|std::views::filter([&](Entity&ent){return ent.IsFriendly()!=friendly;})){
|
||||
ent.Hurt(damage*settings.attackMult,OnUpperLevel(),GetZ());
|
||||
}
|
||||
damageTickTimer+=settings.tickRate;
|
||||
}
|
||||
|
||||
if((lightningTickTimer-=fElapsedTime)<=0.f){
|
||||
if(foundTargets.size()==0){
|
||||
for(int i:std::ranges::iota_view(0,1000)){
|
||||
vf2d lightningBoltRandomPos=pos+vf2d{settings.range/100.f*24/1.5f,util::random(2*PI)}.cart();
|
||||
lightning.DrawLightningBolt(lightningBoltRandomPos);
|
||||
}
|
||||
}else{
|
||||
for(Entity&ent:foundTargets|std::views::filter([&](Entity&ent){return ent.IsFriendly()!=friendly;})){
|
||||
for(int i:std::ranges::iota_view(0,1000)){
|
||||
lightning.DrawLightningBolt(ent.GetPos());
|
||||
}
|
||||
}
|
||||
}
|
||||
lightningTickTimer+=settings.lightningBoltTickRate;
|
||||
}
|
||||
|
||||
lightning.Update(fElapsedTime);
|
||||
HomingBullet::Update(fElapsedTime);
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ All rights reserved.
|
||||
#define VERSION_MAJOR 1
|
||||
#define VERSION_MINOR 3
|
||||
#define VERSION_PATCH 0
|
||||
#define VERSION_BUILD 13031
|
||||
#define VERSION_BUILD 13059
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
||||
@ -1466,7 +1466,7 @@ MonsterStrategy
|
||||
|
||||
Thunder Orb Movespeed = 60%
|
||||
Thunder Orb Tick Rate = 1s
|
||||
Thunder Orb Lightning Bolt Tick Rate = 0.2s
|
||||
Thunder Orb Lightning Bolt Tick Rate = 0.05s
|
||||
Thunder Orb Range = 100
|
||||
Thunder Orb Attack Mult = 1.0x
|
||||
Thunder Orb Lifetime = 12.0s
|
||||
|
||||
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user