Restructure Effect class. Add in black hole and portal graphics. Added custom code analysis ruleset. Implemented Blink Portal enchant. Release Build 11230.

pull/65/head
sigonasr2 3 months ago
parent 57b59f943c
commit 94b324e7a2
  1. 26
      Adventures in Lestoria Tests/EnchantTests.cpp
  2. 9
      Adventures in Lestoria/Adventures in Lestoria.vcxproj
  3. 25
      Adventures in Lestoria/AdventuresInLestoria.cpp
  4. 7
      Adventures in Lestoria/AdventuresInLestoria.h
  5. 6
      Adventures in Lestoria/Animation.cpp
  6. 14
      Adventures in Lestoria/Effect.cpp
  7. 11
      Adventures in Lestoria/Effect.h
  8. 9
      Adventures in Lestoria/FadeInOutEffect.cpp
  9. 23
      Adventures in Lestoria/Player.cpp
  10. 1
      Adventures in Lestoria/PlayerTimerType.h
  11. 2
      Adventures in Lestoria/Version.h
  12. 35
      Adventures in Lestoria/Wizard.cpp
  13. BIN
      Adventures in Lestoria/assets/blackhole.png
  14. 2
      Adventures in Lestoria/assets/config/gfx/gfx.txt
  15. BIN
      Adventures in Lestoria/assets/gamepack.pak
  16. BIN
      Adventures in Lestoria/assets/portal.png
  17. BIN
      Adventures in Lestoria/x64/Release Desktop/CodeAnalysisResultManifest.txt
  18. 5
      CodeAnalysisRuleset.ruleset
  19. BIN
      x64/Release/Adventures in Lestoria.exe

@ -1184,5 +1184,31 @@ namespace EnchantTests
Assert::AreEqual(992,newMonster3.GetHealth(),L"Monster 3 should take half the damage the first target does with the Percing Bolt Enchant");
Assert::AreEqual(992,newMonster4.GetHealth(),L"Monster 4 should take half the damage the first target does with the Percing Bolt Enchant");
}
TEST_METHOD(BlinkPortalNoEnchantCheck){
Game::ChangeClass(player,WIZARD);
Assert::AreEqual("Wizard.Right Click Ability.Cooldown"_F,player->GetRightClickAbility().GetCooldownTime(),L"The original cooldown time should be normal.");
player->SetTestScreenAimingLocation(player->GetPos()+vf2d{16.f,0.f});
player->CheckAndPerformAbility(player->GetRightClickAbility(),testKeyboardInput);
Game::Update(0.f);
Assert::AreEqual(size_t(0),game->GetEffect(EffectType::BLINK_PORTAL).size(),L"There should be no teleport portals spawned.");
Assert::AreEqual("Wizard.Right Click Ability.Cooldown"_F,player->GetRightClickAbility().cooldown,L"The cooldown should be normal.");
Assert::AreEqual("Wizard.Right Click Ability.Mana Cost"_I,player->GetRightClickAbility().manaCost,L"The mana cost should be normal.");
}
TEST_METHOD(BlinkPortalEnchantCheck){
Game::ChangeClass(player,WIZARD);
Game::GiveAndEquipEnchantedRing("Blink Portal");
Assert::AreEqual("Blink Portal"_ENC["COOLDOWN"],player->GetRightClickAbility().GetCooldownTime(),L"The original cooldown time should have been modified by the enchant.");
player->SetTestScreenAimingLocation(player->GetPos()+vf2d{16.f,0.f});
player->CheckAndPerformAbility(player->GetRightClickAbility(),testKeyboardInput);
Game::Update(0.f);
Assert::AreEqual(size_t(1),game->GetEffect(EffectType::BLINK_PORTAL).size(),L"There should be a teleport portal spawned.");
Assert::AreEqual(0.f,player->GetRightClickAbility().cooldown,L"The cooldown should be zero since we can activate Teleport again.");
Assert::AreEqual(0,player->GetRightClickAbility().manaCost,L"The mana cost should be zero.");
player->CheckAndPerformAbility(player->GetRightClickAbility(),testKeyboardInput);
Game::Update(0.25f);
Assert::AreEqual(size_t(0),game->GetEffect(EffectType::BLINK_PORTAL).size(),L"Teleport portal should be despawned.");
Assert::AreEqual(player->GetRightClickAbility().GetCooldownTime()-0.25f,player->GetRightClickAbility().cooldown,L"The cooldown should be normal again.");
Assert::AreEqual("Wizard.Right Click Ability.Mana Cost"_I,player->GetRightClickAbility().manaCost,L"The mana cost should be normal again.");
}
};
}

@ -130,6 +130,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Desktop|x64'">
<OutDir>$(SolutionDir)$(PlatformTarget)\Release</OutDir>
<CodeAnalysisRuleSet>..\CodeAnalysisRuleset.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IncludePath>$(IncludePath)</IncludePath>
@ -140,11 +141,19 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IncludePath>$(VCInstallDir)Auxiliary\VS\UnitTest\include;$(IncludePath)</IncludePath>
<LibraryPath>$(VCInstallDir)Auxiliary\VS\UnitTest\lib;$(LibraryPath)</LibraryPath>
<CodeAnalysisRuleSet>..\CodeAnalysisRuleset.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unit Testing|x64'">
<IncludePath>$(VCInstallDir)Auxiliary\VS\UnitTest\include;$(IncludePath)</IncludePath>
<LibraryPath>$(VCInstallDir)Auxiliary\VS\UnitTest\lib;$(LibraryPath)</LibraryPath>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<CodeAnalysisRuleSet>..\CodeAnalysisRuleset.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Emscripten|x64'">
<CodeAnalysisRuleSet>..\CodeAnalysisRuleset.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Emscripten Debug|x64'">
<CodeAnalysisRuleSet>..\CodeAnalysisRuleset.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>

@ -2222,17 +2222,22 @@ void AiL::RenderCooldowns(){
}
}
void AiL::AddEffect(std::unique_ptr<Effect>foreground,std::unique_ptr<Effect> background){
std::pair<ForegroundWrapper,BackgroundWrapper>AiL::AddEffect(std::unique_ptr<Effect>foreground,std::unique_ptr<Effect> background){
ForegroundWrapper foregroundRef{*foreground};
BackgroundWrapper backgroundRef{*background};
AddEffect(std::move(background),true);
AddEffect(std::move(foreground));
return {foregroundRef,backgroundRef};
}
void AiL::AddEffect(std::unique_ptr<Effect> foreground,bool back){
Effect&AiL::AddEffect(std::unique_ptr<Effect> foreground,bool back){
ForegroundWrapper effectRef{*foreground};
if(back){
backgroundEffectsToBeInserted.push_back(std::move(foreground));
backgroundEffectsToBeInserted.emplace_back(std::move(foreground));
} else {
foregroundEffectsToBeInserted.push_back(std::move(foreground));
foregroundEffectsToBeInserted.emplace_back(std::move(foreground));
}
return effectRef;
}
vf2d AiL::GetWorldMousePos(){
@ -4586,11 +4591,12 @@ std::vector<Effect*>AiL::GetBackgroundEffects()const{
std::for_each(backgroundEffects.begin(),backgroundEffects.end(),[&outputVec](const std::unique_ptr<Effect>&eff){outputVec.emplace_back(eff.get());});
return outputVec;
}
std::vector<Effect*>AiL::GetAllEffects()const{
[[nodiscard]]std::vector<Effect*>AiL::GetAllEffects()const{
std::vector<Effect*>outputVec;
std::vector<Effect*>foregroundEffects{GetForegroundEffects()};
std::vector<Effect*>backgroundEffects{GetBackgroundEffects()};
std::merge(foregroundEffects.begin(),foregroundEffects.end(),backgroundEffects.begin(),backgroundEffects.end(),std::back_inserter(outputVec));
std::copy(foregroundEffects.begin(),foregroundEffects.end(),std::back_inserter(outputVec));
std::copy(backgroundEffects.begin(),backgroundEffects.end(),std::back_inserter(outputVec));
return outputVec;
}
@ -4676,3 +4682,10 @@ void AiL::AddNotification(const Notification&n){
}
AiL::Notification::Notification(const std::string_view message,const float time,const Pixel col)
:message(message),time(time),col(col){}
const std::vector<Effect*>AiL::GetEffect(EffectType type){
std::vector<Effect*>effects{GetAllEffects()};
std::vector<Effect*>matchingEffects{};
std::copy_if(effects.begin(),effects.end(),std::back_inserter(matchingEffects),[&type](const Effect*effect){return effect->GetType()==type;});
return matchingEffects;
}

@ -74,6 +74,8 @@ using HurtListItem=std::pair<std::variant<Monster*,Player*>,HurtReturnValue>;
using HurtList=std::vector<HurtListItem>;
using StackCount=uint8_t;
using MarkTime=float;
using ForegroundWrapper=std::reference_wrapper<Effect>;
using BackgroundWrapper=std::reference_wrapper<Effect>;
enum class KnockbackCondition{
KNOCKBACK_HURT_TARGETS, //Knockback only targets that took damage.
@ -269,9 +271,10 @@ public:
void RenderHud();
void RenderMenu();
bool MenuClicksDeactivated()const;
void AddEffect(std::unique_ptr<Effect>foreground,std::unique_ptr<Effect>background);
std::pair<ForegroundWrapper,BackgroundWrapper>AddEffect(std::unique_ptr<Effect>foreground,std::unique_ptr<Effect>background);
//If back is true, places the effect in the background
void AddEffect(std::unique_ptr<Effect>foreground,bool back=false);
Effect&AddEffect(std::unique_ptr<Effect>foreground,bool back=false);
const std::vector<Effect*>GetEffect(EffectType type);
const HurtList Hurt(vf2d pos,float radius,int damage,bool upperLevel,float z,const HurtType hurtTargets,HurtFlag::HurtFlag hurtFlags=HurtFlag::NONE)const;
const HurtList HurtMonsterType(vf2d pos,float radius,int damage,bool upperLevel,float z,const std::string_view monsterName,HurtFlag::HurtFlag hurtFlags=HurtFlag::NONE)const;
//NOTE: This function will also add any enemies that were hit into the hit list!

@ -452,6 +452,12 @@ void sig::Animation::InitializeAnimations(){
CreateHorizontalAnimationSequence("explosive_trap.png",4,{48,48},AnimationData{.frameDuration{0.06f},.style{Animate2D::Style::PingPong}});
CreateHorizontalAnimationSequence("explosionframes.png",21,{24,24},AnimationData{.frameDuration{0.02f},.style{Animate2D::Style::OneShot}});
CreateHorizontalAnimationSequence("portal.png",8,{24,24},AnimationData{.frameDuration{0.1f},.style{Animate2D::Style::Repeat}});
//!!!!!WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//DO NOT CREATE MORE ANIMATION SEQUENCES UNDERNEATH HERE AS THE NEXT BLOCK WILL CREATE DEFAULT ANIMATIONS
//FOR ALL NON-SPECIFIED ANIMATION SEQUENCES!
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
for(auto&dat:GFX){
std::string imgFile=dat.first;
if(!ANIMATION_DATA.count(imgFile)){

@ -45,15 +45,15 @@ INCLUDE_game
INCLUDE_GFX
Effect::Effect(vf2d pos,float lifetime,const std::string&imgFile,bool upperLevel,float size,float fadeout,vf2d spd,Pixel col,float rotation,float rotationSpd,bool additiveBlending)
:Effect::Effect(pos,lifetime,imgFile,upperLevel,0.f,fadeout,vf2d{size,size},spd,col,rotation,rotationSpd,additiveBlending){}
:Effect(pos,lifetime,imgFile,upperLevel,0.f,fadeout,vf2d{size,size},spd,col,rotation,rotationSpd,additiveBlending){}
Effect::Effect(vf2d pos,float lifetime,const std::string&imgFile,bool upperLevel,vf2d size,float fadeout,vf2d spd,Pixel col,float rotation,float rotationSpd,bool additiveBlending)
:pos(pos),lifetime(lifetime),upperLevel(upperLevel),size(size),fadeout(fadeout),original_fadeOutTime(fadeout),spd(spd),col(col),rotation(rotation),rotationSpd(rotationSpd),additiveBlending(additiveBlending){
this->animation.AddState(imgFile,ANIMATION_DATA.at(imgFile));
this->animation.ChangeState(internal_animState,imgFile);
}
:Effect(pos,lifetime,imgFile,upperLevel,0.f,fadeout,size,spd,col,rotation,rotationSpd,additiveBlending){}
Effect::Effect(vf2d pos,float lifetime,const std::string&imgFile,bool upperLevel,float fadein,float fadeout,vf2d size,vf2d spd,Pixel col,float rotation,float rotationSpd,bool additiveBlending)
:Effect(pos,lifetime,imgFile,upperLevel,fadein,fadeout,size,spd,EffectType::NONE,col,rotation,rotationSpd,additiveBlending){}
Effect::Effect(vf2d pos,float lifetime,const std::string&imgFile,bool upperLevel,float fadein,float fadeout,vf2d size,vf2d spd,EffectType type,Pixel col,float rotation,float rotationSpd,bool additiveBlending)
:pos(pos),lifetime(lifetime),upperLevel(upperLevel),size(size),fadein(fadein),original_fadeInTime(fadein),fadeout(fadeout),original_fadeOutTime(fadeout),spd(spd),col(col),rotation(rotation),rotationSpd(rotationSpd),additiveBlending(additiveBlending){
this->animation.AddState(imgFile,ANIMATION_DATA.at(imgFile));
this->animation.ChangeState(internal_animState,imgFile);
@ -116,3 +116,7 @@ const EffectType Effect::GetType()const{
const float Effect::GetZ()const{
return z;
}
void Effect::SetType(const EffectType type){
this->type=type;
}

@ -43,11 +43,15 @@ All rights reserved.
class Monster;
class Player;
using HitList=std::unordered_set<std::variant<Monster*,Player*>>;
using OscillatorVf2d=std::pair<vf2d,vf2d>;
using OscillatorPixel=std::pair<Pixel,Pixel>;
enum class EffectType{
NONE,
SPELL_CIRCLE,
MONSTER_SOUL,
BLINK_PORTAL,
BLACK_HOLE,
};
struct Effect{
@ -71,12 +75,14 @@ public:
Effect(vf2d pos,float lifetime,const std::string&imgFile,bool upperLevel,float size=1.0f,float fadeout=0.0f,vf2d spd={},Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false);
Effect(vf2d pos,float lifetime,const std::string&imgFile,bool upperLevel,vf2d size={1,1},float fadeout=0.0f,vf2d spd={},Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false);
Effect(vf2d pos,float lifetime,const std::string&imgFile,bool upperLevel,float fadein,float fadeout,vf2d size,vf2d spd,Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false);
Effect(vf2d pos,float lifetime,const std::string&imgFile,bool upperLevel,float fadein,float fadeout,vf2d size,vf2d spd,EffectType type,Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false);
virtual bool Update(float fElapsedTime);
Animate2D::Frame GetFrame()const;
virtual void Draw()const;
bool OnUpperLevel();
const EffectType GetType()const;
const float GetZ()const;
void SetType(const EffectType type);
protected:
float original_fadeOutTime;
float original_fadeInTime{};
@ -166,12 +172,17 @@ public:
struct FadeInOutEffect:Effect{
//cycleSpd is how long it takes to get from fully opaque to fully transparent, and back to fully opaque
FadeInOutEffect(vf2d pos,const std::string&img,float lifetime,float cycleSpd,bool onUpperLevel,float size,vf2d spd,Pixel col,float rotation,float rotationSpd,bool additiveBlending=false,float particleSpawnFreq=0.f,const std::function<Effect()>&particleGenerator={});
//A version with oscillators for position and colors, for extra animation effects!
FadeInOutEffect(OscillatorVf2d pos,const std::string&img,float lifetime,float cycleSpd,bool onUpperLevel,float size,vf2d spd,OscillatorPixel col,float rotation,float rotationSpd,bool additiveBlending=false,float particleSpawnFreq=0.f,const std::function<Effect()>&particleGenerator={});
virtual bool Update(float fElapsedTime)override;
virtual void Draw()const override;
std::function<Effect()>particleGenerator;
const float particleSpawnFreq;
const float cycleSpd;
const OscillatorVf2d posOscillator;
const OscillatorPixel colOscillator;
float particleSpawnTimer{};
const float originalParticleSpawnTimer{};
};

@ -43,7 +43,9 @@ All rights reserved.
INCLUDE_game
FadeInOutEffect::FadeInOutEffect(vf2d pos,const std::string&img,float lifetime,float cycleSpd,bool onUpperLevel,float size,vf2d spd,Pixel col,float rotation,float rotationSpd,bool additiveBlending,float particleSpawnFreq,const std::function<Effect()>&particleGenerator)
:particleSpawnFreq(particleSpawnFreq),particleGenerator(particleGenerator),cycleSpd(cycleSpd),particleSpawnTimer(particleSpawnFreq),originalParticleSpawnTimer(particleSpawnTimer),Effect(pos,lifetime,img,onUpperLevel,size,0.25f,spd,col,rotation,rotationSpd,additiveBlending){}
:FadeInOutEffect({pos,pos},img,lifetime,cycleSpd,onUpperLevel,size,spd,{col,col},rotation,rotationSpd,additiveBlending,particleSpawnFreq,particleGenerator){}
FadeInOutEffect::FadeInOutEffect(OscillatorVf2d pos,const std::string&img,float lifetime,float cycleSpd,bool onUpperLevel,float size,vf2d spd,OscillatorPixel col,float rotation,float rotationSpd,bool additiveBlending,float particleSpawnFreq,const std::function<Effect()>&particleGenerator)
:particleSpawnFreq(particleSpawnFreq),particleGenerator(particleGenerator),cycleSpd(cycleSpd),particleSpawnTimer(particleSpawnFreq),originalParticleSpawnTimer(particleSpawnTimer),posOscillator(pos),colOscillator(col),Effect(pos.first,lifetime,img,onUpperLevel,size,0.25f,spd,col.first,rotation,rotationSpd,additiveBlending){}
bool FadeInOutEffect::Update(float fElapsedTime){
if(particleGenerator){
particleSpawnTimer-=fElapsedTime;
@ -52,7 +54,10 @@ bool FadeInOutEffect::Update(float fElapsedTime){
game->AddEffect(std::make_unique<Effect>(particleGenerator()));
}
}
col.a=abs(sin(PI*game->GetRunTime()*cycleSpd))*255;
float t{float(abs(sin(PI*game->GetRunTime()*cycleSpd)))};
pos=posOscillator.first.lerp(posOscillator.second,t);
col=PixelLerp(colOscillator.first,colOscillator.second,t);
col.a=t*255;
return Effect::Update(fElapsedTime);
}
void FadeInOutEffect::Draw()const{

@ -1223,6 +1223,7 @@ CastInfo&Player::GetCastInfo(){
}
bool Player::CanPathfindTo(vf2d pos,vf2d targetPos,float range){
if(game->TestingModeEnabled())return true;
range*=(24/game->pathfinder.gridSpacing.x);
if(targetPos.x<0||targetPos.y<0||targetPos.x>game->GetCurrentMapData().width*game->GetCurrentMapData().tilewidth||targetPos.y>game->GetCurrentMapData().height*game->GetCurrentMapData().tileheight)return false;
std::vector<vf2d>pathing=game->pathfinder.Solve_AStar(pos,targetPos,range,upperLevel);
@ -1530,6 +1531,10 @@ void Player::RecalculateEquipStats(){
if(HasEnchant("Nine Lives"))GetRightClickAbility().COOLDOWN_TIME="Nine Lives"_ENC["TRANSFORM COOLDOWN"];
}
if(GetClass()&WIZARD){
if(HasEnchant("Blink Portal"))GetRightClickAbility().COOLDOWN_TIME="Blink Portal"_ENC["COOLDOWN"];
}
for(const std::reference_wrapper<Ability>&a:GetAbilities()){
if(a.get().itemAbility)continue;
if(a.get().charges<a.get().MAX_CHARGES&&a.get().cooldown==0.f)a.get().cooldown=a.get().GetCooldownTime();
@ -2074,6 +2079,24 @@ void Player::OnAbilityUse(const Ability&ability){
if(UsedAbility("Transform")&&HasEnchant("Nine Lives")){
if(HasTimer(PlayerTimerType::CAT_FORM_ALREADY_ACTIVE)&&GetTimer(PlayerTimerType::CAT_FORM_ALREADY_ACTIVE).IsRunning())Witch::rightClickAbility.cooldown="Witch.Right Click Ability.Cooldown"_F;
}
if(UsedAbility("Teleport")&&HasEnchant("Blink Portal")){
const bool IsPortalTeleport{Wizard::rightClickAbility.manaCost!=0.f};
if(IsPortalTeleport){
Wizard::rightClickAbility.charges++;
Wizard::rightClickAbility.manaCost=0;
Wizard::rightClickAbility.cooldown=0.f;
AddTimer(PlayerTimerType::BLINK_PORTAL_SECOND_CAST,Timer{"Blink Portal Second Cast","Blink Portal"_ENC["REACTIVATION TIME"],[](){
Wizard::rightClickAbility.manaCost="Wizard.Right Click Ability.Mana Cost"_I;
Wizard::rightClickAbility.cooldown="Blink Portal"_ENC["COOLDOWN"];
Wizard::rightClickAbility.charges--;
},Timer::MANUAL});
}else{
Wizard::rightClickAbility.manaCost="Wizard.Right Click Ability.Mana Cost"_I;
Wizard::rightClickAbility.cooldown="Blink Portal"_ENC["COOLDOWN"];
CancelTimer(PlayerTimerType::BLINK_PORTAL_SECOND_CAST);
}
}
}
Ability&Player::GetItem1(){

@ -44,4 +44,5 @@ enum class PlayerTimerType{
OPPORTUNITY_SHOT_RANDOM_SPECIAL_MARK,
ADVANCE_SHIELD_TIMER,
CAT_FORM_ALREADY_ACTIVE,
BLINK_PORTAL_SECOND_CAST,
};

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 1
#define VERSION_MINOR 2
#define VERSION_PATCH 5
#define VERSION_BUILD 11202
#define VERSION_BUILD 11230
#define stringify(a) stringify_(a)
#define stringify_(a) #a

@ -132,18 +132,33 @@ void Wizard::InitializeClassAbilities(){
#pragma region lambdas
auto NoPlayerCollisionWithTile=[&](){return !geom2d::overlaps(geom2d::circle<float>(teleportPoint,4),collisionRect);};
#pragma endregion
if(p->lastPathfindingCooldown==0.f){
if(dist>0&&p->CanPathfindTo(p->GetPos(),teleportPoint,float("Wizard.Right Click Ability.TilesMax"_I))
const auto TeleportTo=[&p](const vf2d pos){
p->SetState(State::TELEPORT);
p->teleportAnimationTimer="Wizard.Right Click Ability.AnimationTime"_F;
p->teleportTarget=pos;
p->teleportStartPosition=p->GetPos();
p->ApplyIframes("Wizard.Right Click Ability.IframeTime"_F);
for(int i=0;i<"Wizard.Right Click Ability.ParticleCount"_I;i++){
game->AddEffect(std::make_unique<Effect>(p->GetPos()+vf2d{(util::random("Wizard.Right Click Ability.ParticleRange"_F/100*2)-"Wizard.Right Click Ability.ParticleRange"_F/100)*12,(util::random("Wizard.Right Click Ability.ParticleRange"_F/100*2)-"Wizard.Right Click Ability.ParticleRange"_F/100)*12},util::random("Wizard.Right Click Ability.ParticleLifetimeMax"_F)+"Wizard.Right Click Ability.ParticleLifetimeMin"_F,"circle.png",p->upperLevel,"Wizard.Right Click Ability.ParticleSize"_F,"Wizard.Right Click Ability.ParticleFadetime"_F,vf2d{util::random("Wizard.Right Click Ability.ParticleSpeedMax"_F*2)+"Wizard.Right Click Ability.ParticleSpeedMin"_F,util::random("Wizard.Right Click Ability.ParticleSpeedMax"_F*2)+"Wizard.Right Click Ability.ParticleSpeedMin"_F},"Wizard.Right Click Ability.ParticleColor"_Pixel));
}
SoundEffect::PlaySFX("Wizard Teleport",SoundEffect::CENTERED);
};
std::vector<Effect*>portals{game->GetEffect(EffectType::BLINK_PORTAL)};
if(portals.size()>0){
TeleportTo(portals[0]->pos);
portals[0]->lifetime=0.f;
portals[0]->fadeout=0.25f;
return true;
}else if(p->lastPathfindingCooldown==0.f){
if(game->TestingModeEnabled()||dist>0&&p->CanPathfindTo(p->GetPos(),teleportPoint,float("Wizard.Right Click Ability.TilesMax"_I))
&&(NoTileCollisionExistsHere()||NoPlayerCollisionWithTile())){
p->SetState(State::TELEPORT);
p->teleportAnimationTimer="Wizard.Right Click Ability.AnimationTime"_F;
p->teleportTarget=teleportPoint;
p->teleportStartPosition=p->GetPos();
p->ApplyIframes("Wizard.Right Click Ability.IframeTime"_F);
for(int i=0;i<"Wizard.Right Click Ability.ParticleCount"_I;i++){
game->AddEffect(std::make_unique<Effect>(p->GetPos()+vf2d{(util::random("Wizard.Right Click Ability.ParticleRange"_F/100*2)-"Wizard.Right Click Ability.ParticleRange"_F/100)*12,(util::random("Wizard.Right Click Ability.ParticleRange"_F/100*2)-"Wizard.Right Click Ability.ParticleRange"_F/100)*12},util::random("Wizard.Right Click Ability.ParticleLifetimeMax"_F)+"Wizard.Right Click Ability.ParticleLifetimeMin"_F,"circle.png",p->upperLevel,"Wizard.Right Click Ability.ParticleSize"_F,"Wizard.Right Click Ability.ParticleFadetime"_F,vf2d{util::random("Wizard.Right Click Ability.ParticleSpeedMax"_F*2)+"Wizard.Right Click Ability.ParticleSpeedMin"_F,util::random("Wizard.Right Click Ability.ParticleSpeedMax"_F*2)+"Wizard.Right Click Ability.ParticleSpeedMin"_F},"Wizard.Right Click Ability.ParticleColor"_Pixel));
if(p->HasEnchant("Blink Portal")){
Effect&eff{game->AddEffect(std::make_unique<FadeInOutEffect>(OscillatorVf2d{p->GetPos(),p->GetPos()+vf2d{0,-6.f}},"portal.png","Blink Portal"_ENC["REACTIVATION TIME"],0.5f,p->OnUpperLevel(),1.f,vf2d{},OscillatorPixel{WHITE,0x50196f},0.f,0.f),true)};
eff.SetType(EffectType::BLINK_PORTAL);
}
SoundEffect::PlaySFX("Wizard Teleport",SoundEffect::CENTERED);
TeleportTo(teleportPoint);
p->lastPathfindingCooldown=0.1f;
return true;
} else {

Binary file not shown.

After

Width:  |  Height:  |  Size: 983 B

@ -125,6 +125,8 @@ Images
GFX_MonsterSoulGlow = monstersoulglow.png
GFX_Glow = glow.png
GFX_SpecialTargetMark = special_target.png
GFX_BlackHole = blackhole.png
GFX_Portal = portal.png
GFX_Thief_Sheet = nico-thief.png
GFX_Trapper_Sheet = nico-trapper.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="CodeAnalysisRuleset" ToolsVersion="17.0">
<Include Path="codeanalysisruleset.ruleset" Action="Default" />
<Include Path="nativerecommendedrules.ruleset" Action="Default" />
</RuleSet>
Loading…
Cancel
Save