From 2c54e9a9c71ba29837934277f6d23bba27033f93 Mon Sep 17 00:00:00 2001 From: sigonasr2 Date: Fri, 12 Jan 2024 09:56:49 -0600 Subject: [PATCH] Monsters get a 1-second cooldown on collision to avoid overwhelming the player through constant charging. Remove extra A* nodes that are not required during map loading. Reversed the surround sound directions so stuff on the right is heard from the right channel, and stuff on the left is heard from the left channel. Fix lerp function in olcPGEX geometry util. --- .../AdventuresInLestoria.cpp | 11 ++-- Adventures in Lestoria/EnvironmentalAudio.cpp | 2 +- Adventures in Lestoria/Monster.cpp | 53 ++++++++++++++++--- Adventures in Lestoria/Monster.h | 15 +++++- Adventures in Lestoria/Pathfinding.cpp | 11 ++++ Adventures in Lestoria/Player.cpp | 32 +++++++++-- Adventures in Lestoria/Player.h | 10 ++++ Adventures in Lestoria/RunAway.cpp | 23 ++++++-- Adventures in Lestoria/RunTowards.cpp | 13 +++-- Adventures in Lestoria/ShootAfar.cpp | 19 ++++++- Adventures in Lestoria/SoundEffect.cpp | 2 +- Adventures in Lestoria/Version.h | 2 +- Adventures in Lestoria/Wizard.cpp | 13 ++++- .../assets/config/items/items.txt | 2 +- Adventures in Lestoria/olcUTIL_Geometry2D.h | 7 ++- 15 files changed, 182 insertions(+), 33 deletions(-) diff --git a/Adventures in Lestoria/AdventuresInLestoria.cpp b/Adventures in Lestoria/AdventuresInLestoria.cpp index 7d78e3a8..5c2c7d87 100644 --- a/Adventures in Lestoria/AdventuresInLestoria.cpp +++ b/Adventures in Lestoria/AdventuresInLestoria.cpp @@ -804,6 +804,7 @@ void AiL::RenderWorld(float fElapsedTime){ if(player->teleportAnimationTimer>0){ playerScale.x=120*float(abs(pow(player->teleportAnimationTimer-"Wizard.Right Click Ability.AnimationTime"_F/2,3))); pos=player->teleportStartPosition.lerp(player->teleportTarget,("Wizard.Right Click Ability.AnimationTime"_F-player->teleportAnimationTimer)/"Wizard.Right Click Ability.AnimationTime"_F); + std::cout<attackBuffs=player->GetStatBuffs({"Attack","Attack %"}); view.DrawPartialRotatedDecal(pos+vf2d{0,-player->GetZ()*(std::signbit(scale.y)?-1:1)},player->GetFrame().GetSourceImage()->Decal(),player->GetSpinAngle(),{12,12},player->GetFrame().GetSourceRect().pos,player->GetFrame().GetSourceRect().size,playerScale*scale,attackBuffs.size()>0?Pixel{255,uint8_t(255*abs(sin(1.4*attackBuffs[0].duration))),uint8_t(255*abs(sin(1.4*attackBuffs[0].duration)))}:WHITE); @@ -957,11 +958,13 @@ void AiL::RenderWorld(float fElapsedTime){ for(int x2=0;x2<2;x2++){ vf2d tilePos=vf2d{float(x),float(y)}*24; vf2d gridPos=tilePos+pathfinder.gridSpacing*vf2d{float(x2),float(y2)}; - Pixel col=RED; - if(!pathfinder.nodes[gridPos].bObstacle&&!pathfinder.nodes[gridPos].bObstacleUpper){ - col=GREEN; + if(pathfinder.nodes.count(gridPos)){ + Pixel col=RED; + if(!pathfinder.nodes[gridPos].bObstacle&&!pathfinder.nodes[gridPos].bObstacleUpper){ + col=GREEN; + } + view.FillRectDecal(gridPos,pathfinder.gridSpacing,{col.r,col.g,col.b,128}); } - view.FillRectDecal(gridPos,pathfinder.gridSpacing,{col.r,col.g,col.b,128}); } } } diff --git a/Adventures in Lestoria/EnvironmentalAudio.cpp b/Adventures in Lestoria/EnvironmentalAudio.cpp index 9edad25e..b432c73b 100644 --- a/Adventures in Lestoria/EnvironmentalAudio.cpp +++ b/Adventures in Lestoria/EnvironmentalAudio.cpp @@ -92,7 +92,7 @@ void EnvironmentalAudio::Update(){ return; //Do not need to continue processing if the sound is not even going to be heard. } float distRatio=1-distanceFromPlayer/ACTIVATION_RANGE; //0-1 where 1 is full volume. - float xDistRatio=(pos.x-game->GetPlayer()->GetX())/ACTIVATION_RANGE; //0-1 where 1 is full volume. + float xDistRatio=(game->GetPlayer()->GetX()-pos.x)/ACTIVATION_RANGE; //0-1 where 1 is full volume. Audio::Engine().SetVolume(soundInstance,distRatio*SOUND_DATA[audioName].volume); Audio::Engine().SetPan(soundInstance,xDistRatio); diff --git a/Adventures in Lestoria/Monster.cpp b/Adventures in Lestoria/Monster.cpp index c7e38c2f..5b93d57e 100644 --- a/Adventures in Lestoria/Monster.cpp +++ b/Adventures in Lestoria/Monster.cpp @@ -113,7 +113,7 @@ void Monster::PerformShootAnimation(){ void Monster::PerformIdleAnimation(){ animation.ChangeState(internal_animState,MONSTER_DATA[name].GetIdleAnimation()); } -bool Monster::SetX(float x){ +bool Monster::_SetX(float x,const bool monsterInvoked){ vf2d newPos={x,pos.y}; vi2d tilePos=vi2d(newPos/float(game->GetCurrentMapData().tilewidth))*game->GetCurrentMapData().tilewidth; geom2d::rectcollisionRect=game->GetTileCollision(game->GetCurrentLevel(),newPos,upperLevel); @@ -123,16 +123,27 @@ bool Monster::SetX(float x){ return true; } else { geom2d::rectcollision={collisionRect.pos,collisionRect.size}; + #pragma region lambdas + auto NoEnemyCollisionWithTile=[&](){return !geom2d::overlaps(geom2d::circle(newPos,game->GetCurrentMapData().tilewidth/2*GetSizeMult()),collision);}; + #pragma endregion collision.pos+=tilePos; - if(!geom2d::overlaps(geom2d::circle(newPos,12*GetSizeMult()),collision)){ + if(NoEnemyCollisionWithTile()){ pos.x=std::clamp(x,game->GetCurrentMapData().tilewidth/2.f*GetSizeMult(),float(game->GetCurrentMapData().width*game->GetCurrentMapData().tilewidth-game->GetCurrentMapData().tilewidth/2.f*GetSizeMult())); Moved(); return true; + }else + if(monsterInvoked){ //If player invoked, we'll try the smart move system. + vf2d pushDir=geom2d::line(collision.middle(),pos).vector().norm(); + newPos={newPos.x,pos.y+pushDir.y*12}; + if(NoEnemyCollisionWithTile()){ + return _SetY(pos.y+pushDir.y,false); + } } } return false; } -bool Monster::SetY(float y){ + +bool Monster::_SetY(float y,const bool monsterInvoked){ vf2d newPos={pos.x,y}; vi2d tilePos=vi2d(newPos/float(game->GetCurrentMapData().tilewidth))*game->GetCurrentMapData().tilewidth; geom2d::rectcollisionRect=game->GetTileCollision(game->GetCurrentLevel(),newPos,upperLevel); @@ -142,19 +153,39 @@ bool Monster::SetY(float y){ return true; } else { geom2d::rectcollision={collisionRect.pos,collisionRect.size}; + #pragma region lambdas + auto NoEnemyCollisionWithTile=[&](){return !geom2d::overlaps(geom2d::circle(newPos,game->GetCurrentMapData().tilewidth/2*GetSizeMult()),collision);}; + #pragma endregion collision.pos+=tilePos; - if(!geom2d::overlaps(geom2d::circle(newPos,game->GetCurrentMapData().tilewidth/2*GetSizeMult()),collision)){ + if(NoEnemyCollisionWithTile()){ pos.y=std::clamp(y,game->GetCurrentMapData().tilewidth/2.f*GetSizeMult(),float(game->GetCurrentMapData().height*game->GetCurrentMapData().tilewidth-game->GetCurrentMapData().tilewidth/2.f*GetSizeMult())); Moved(); return true; + }else + if(monsterInvoked){ //If player invoked, we'll try the smart move system.{ + vf2d pushDir=geom2d::line(collision.middle(),pos).vector().norm(); + newPos={pos.x+pushDir.x*12,newPos.y}; + if(NoEnemyCollisionWithTile()){ + return _SetX(pos.x+pushDir.x,false); + } } } return false; } + +bool Monster::SetX(float x){ + return _SetX(x); +} + +bool Monster::SetY(float y){ + return _SetY(y); +} + bool Monster::Update(float fElapsedTime){ lastHitTimer=std::max(0.f,lastHitTimer-fElapsedTime); iframe_timer=std::max(0.f,iframe_timer-fElapsedTime); monsterHurtSoundCooldown=std::max(0.f,monsterHurtSoundCooldown-fElapsedTime); + lastHitPlayer=std::max(0.f,lastHitPlayer-fElapsedTime); if(size!=targetSize){ if(size>targetSize){ @@ -270,9 +301,9 @@ void Monster::DrawReflection(float drawRatioX,float multiplierX){ game->SetDecalMode(DecalMode::NORMAL); } void Monster::Collision(Player*p){ - if(MONSTER_DATA[name].GetCollisionDmg()>0&&!hasHitPlayer){ + if(MONSTER_DATA[name].GetCollisionDmg()>0&&lastHitPlayer==0.0f){ if(p->Hurt(MONSTER_DATA[name].GetCollisionDmg(),OnUpperLevel(),GetZ())){ - hasHitPlayer=true; + lastHitPlayer=1.0f; } } Collision(); @@ -419,7 +450,7 @@ void Monster::AddBuff(BuffType type,float duration,float intensity){ buffList.push_back(Buff{type,duration,intensity}); } -void Monster::StartPathfinding(float pathingTime){ +bool Monster::StartPathfinding(float pathingTime){ SetState(State::PATH_AROUND); path=game->pathfinder.Solve_WalkPath(pos,target,12,OnUpperLevel()); if(path.points.size()>0){ @@ -427,6 +458,7 @@ void Monster::StartPathfinding(float pathingTime){ //We gives this mob 5 seconds to figure out a path to the target. targetAcquireTimer=pathingTime; } + return path.points.size()>0; } void Monster::PathAroundBehavior(float fElapsedTime){ @@ -434,7 +466,12 @@ void Monster::PathAroundBehavior(float fElapsedTime){ //Move towards the new path. geom2d::line moveTowardsLine=geom2d::line(pos,path.GetSplinePoint(pathIndex).pos); if(moveTowardsLine.length()>2){ - SetPos(pos+moveTowardsLine.vector().norm()*100*fElapsedTime*GetMoveSpdMult()); + if(!SetPos(pos+moveTowardsLine.vector().norm()*100*fElapsedTime*GetMoveSpdMult())){ + //We are stuck, so stop pathfinding. + path.points.clear(); + pathIndex=0; + targetAcquireTimer=0; + } if(moveTowardsLine.vector().x>0){ facingDirection=RIGHT; } else { diff --git a/Adventures in Lestoria/Monster.h b/Adventures in Lestoria/Monster.h index 54b94f6a..d0b79a59 100644 --- a/Adventures in Lestoria/Monster.h +++ b/Adventures in Lestoria/Monster.h @@ -150,7 +150,8 @@ public: void PerformIdleAnimation(); bool OnUpperLevel(); void Moved(); - void StartPathfinding(float pathingTime); + //Returns false if a path could not be found. + bool StartPathfinding(float pathingTime); void PathAroundBehavior(float fElapsedTime); void AddBuff(BuffType type,float duration,float intensity); std::vectorGetBuffs(BuffType buff); @@ -193,7 +194,7 @@ private: float monsterWalkSoundTimer; std::vectorbuffList; std::string GetDeathAnimationName(); - bool hasHitPlayer=false; + float lastHitPlayer=0.0f; bool canMove=true; //Set to false when stuck due to collisions. bool upperLevel=false; vf2d pathTarget={}; @@ -207,6 +208,16 @@ private: bool isBoss=false; void OnDeath(); ItemAttribute&Get(std::string_view attr); + //Returns false if the monster could not be moved to the requested location due to collision. + //If monsterInvoked is true, this means the monster was the one that instantiated this input, and it's not an extra movement done via collision. + //Set monsterInvoked to false when you don't want a movement loop due to collisions. + //Typical usage is monsterInvoked is true on first call, and monsterInvoked is false on all subsequent chained calls. + bool _SetX(float x,const bool monsterInvoked=true); + //Returns false if the monster could not be moved to the requested location due to collision. + //If monsterInvoked is true, this means the monster was the one that instantiated this input, and it's not an extra movement done via collision. + //Set monsterInvoked to false when you don't want a movement loop due to collisions. + //Typical usage is monsterInvoked is true on first call, and monsterInvoked is false on all subsequent chained calls. + bool _SetY(float y,const bool monsterInvoked=true); private: struct STRATEGY{ diff --git a/Adventures in Lestoria/Pathfinding.cpp b/Adventures in Lestoria/Pathfinding.cpp index d7c13a35..af7b8dae 100644 --- a/Adventures in Lestoria/Pathfinding.cpp +++ b/Adventures in Lestoria/Pathfinding.cpp @@ -49,6 +49,16 @@ void Pathfinding::Initialize(){ for (int x = 0; x < game->GetCurrentMapData().width*24; x+=gridSpacing.x) for (int y = 0; y < game->GetCurrentMapData().height*24; y+=gridSpacing.y) { + bool tileIsEmpty=true; + for(const LayerTag&layer:game->GetCurrentMap().LayerData){ + int tileID=layer.tiles[y/24][x/24]-1; + if(tileID!=-1){ + tileIsEmpty=false; + break; + } + } + if(tileIsEmpty)continue; //Don't add the node since it's outside the map. + sNode&node=nodes[{x,y}]; node.x = x; // ...because we give each node its own coordinates node.y = y; // ...because we give each node its own coordinates @@ -184,6 +194,7 @@ std::vector Pathfinding::Solve_AStar(vf2d startPos,vf2d endPos,float maxRa } Pathfinding::sSpline Pathfinding::Solve_WalkPath(vf2d startPos,vf2d endPos,float maxRange,bool upperLevel){ + maxRange*=(24/game->pathfinder.gridSpacing.x); Pathfinding::sSpline newSpline{}; newSpline.Initialize(Solve_AStar(startPos,endPos,maxRange,upperLevel)); return newSpline; diff --git a/Adventures in Lestoria/Player.cpp b/Adventures in Lestoria/Player.cpp index efec135f..6b8ee582 100644 --- a/Adventures in Lestoria/Player.cpp +++ b/Adventures in Lestoria/Player.cpp @@ -102,9 +102,10 @@ void Player::Initialize(){ void Player::ForceSetPos(vf2d pos){ this->pos=pos; + Moved(); } -bool Player::SetX(float x){ +bool Player::_SetX(float x,const bool playerInvoked){ vf2d newPos={x,pos.y}; vi2d tilePos=vi2d(newPos/float(game->GetCurrentMapData().tilewidth))*game->GetCurrentMapData().tilewidth; geom2d::rectcollisionRect=game->GetTileCollision(game->GetCurrentLevel(),newPos,upperLevel); @@ -118,19 +119,26 @@ bool Player::SetX(float x){ } else { geom2d::rectcollision={collisionRect.pos,collisionRect.size}; #pragma region lambdas - auto NoPlayerCollisionWithTile=[&](){return !geom2d::overlaps(newPos,collision);}; + auto NoPlayerCollisionWithTile=[&](){return !geom2d::overlaps(geom2d::circle(newPos,4),collision);}; #pragma endregion collision.pos+=tilePos; if(NoPlayerCollisionWithTile()){ pos.x=std::clamp(x,game->GetCurrentMapData().tilewidth/2.f*GetSizeMult(),float(game->GetCurrentMapData().width*game->GetCurrentMapData().tilewidth-game->GetCurrentMapData().tilewidth/2.f*GetSizeMult())); Moved(); return true; + }else + if(playerInvoked){ //If player invoked, we'll try the smart move system. + vf2d pushDir=geom2d::line(collision.middle(),pos).vector().norm(); + newPos={newPos.x,pos.y+pushDir.y*12}; + if(NoPlayerCollisionWithTile()){ + return _SetY(pos.y+pushDir.y,false); + } } } return false; }; -bool Player::SetY(float y){ +bool Player::_SetY(float y,const bool playerInvoked){ vf2d newPos={pos.x,y}; vi2d tilePos=vi2d(newPos/float(game->GetCurrentMapData().tilewidth))*game->GetCurrentMapData().tilewidth; geom2d::rectcollisionRect=game->GetTileCollision(game->GetCurrentLevel(),newPos,upperLevel); @@ -144,18 +152,33 @@ bool Player::SetY(float y){ } else { geom2d::rectcollision={collisionRect.pos,collisionRect.size}; #pragma region lambdas - auto NoPlayerCollisionWithTile=[&](){return !geom2d::overlaps(newPos,collision);}; + auto NoPlayerCollisionWithTile=[&](){return !geom2d::overlaps(geom2d::circle(newPos,4),collision);}; #pragma endregion collision.pos+=tilePos; if(NoPlayerCollisionWithTile()){ pos.y=std::clamp(y,game->GetCurrentMapData().tilewidth/2.f*GetSizeMult(),float(game->GetCurrentMapData().height*game->GetCurrentMapData().tilewidth-game->GetCurrentMapData().tilewidth/2.f*GetSizeMult())); Moved(); return true; + }else + if(playerInvoked){ //If player invoked, we'll try the smart move system.{ + vf2d pushDir=geom2d::line(collision.middle(),pos).vector().norm(); + newPos={pos.x+pushDir.x*12,newPos.y}; + if(NoPlayerCollisionWithTile()){ + return _SetX(pos.x+pushDir.x,false); + } } } return false; } +bool Player::SetX(float x){ + return _SetX(x); +} + +bool Player::SetY(float y){ + return _SetY(y); +} + void Player::SetZ(float z){ this->z=z; } @@ -824,6 +847,7 @@ CastInfo&Player::GetCastInfo(){ } bool Player::CanPathfindTo(vf2d pos,vf2d targetPos,float range){ + 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::vectorpathing=game->pathfinder.Solve_AStar(pos,targetPos,range,upperLevel); return pathing.size()>0&&pathing.size()=24.f*ConfigInt("Range")/100.f){ m.SetState(State::NORMAL); diff --git a/Adventures in Lestoria/RunTowards.cpp b/Adventures in Lestoria/RunTowards.cpp index 8155a3f9..822e0b00 100644 --- a/Adventures in Lestoria/RunTowards.cpp +++ b/Adventures in Lestoria/RunTowards.cpp @@ -39,6 +39,7 @@ All rights reserved. #include "DEFINES.h" #include "AdventuresInLestoria.h" #include "MonsterStrategyHelpers.h" +#include "util.h" INCLUDE_game INCLUDE_MONSTER_DATA @@ -56,14 +57,20 @@ void Monster::STRATEGY::RUN_TOWARDS(Monster&m,float fElapsedTime,std::string str m.target=desiredTargetLine.upoint(1.2f); } m.SetState(State::MOVE_TOWARDS); - m.hasHitPlayer=false; } switch(m.state){ case State::MOVE_TOWARDS:{ if(geom2d::line(m.pos,m.target).length()>100*fElapsedTime*m.GetMoveSpdMult()){ vf2d newPos=m.pos+geom2d::line(m.pos,m.target).vector().norm()*100*fElapsedTime*m.GetMoveSpdMult(); - if(!m.SetX(newPos.x)||!m.SetY(newPos.y)){ - m.StartPathfinding(4); + if(!m.SetPos(newPos)){ + bool pathFound=m.StartPathfinding(4); + if(!pathFound){ + m.SetState(State::MOVE_TOWARDS); + //Choose a random position around us and move towards it. + float randomAngle=util::random(2*PI); + float randomDist=util::random(24*6); + m.target=m.GetPos()+vf2d{sin(randomAngle),cos(randomAngle)}*randomDist; + } } m.PerformJumpAnimation(); } else { diff --git a/Adventures in Lestoria/ShootAfar.cpp b/Adventures in Lestoria/ShootAfar.cpp index 263c9f1b..2b664ed2 100644 --- a/Adventures in Lestoria/ShootAfar.cpp +++ b/Adventures in Lestoria/ShootAfar.cpp @@ -39,6 +39,7 @@ All rights reserved. #include "DEFINES.h" #include "AdventuresInLestoria.h" #include "MonsterStrategyHelpers.h" +#include "util.h" INCLUDE_BULLET_LIST INCLUDE_game @@ -86,7 +87,14 @@ void Monster::STRATEGY::SHOOT_AFAR(Monster&m,float fElapsedTime,std::string stra m.canMove=movedX&&movedY; } if(!pathfindingDecision){ - m.StartPathfinding(2.5); + bool pathFound=m.StartPathfinding(2.5); + if(!pathFound){ + m.SetState(State::MOVE_TOWARDS); + //Choose a random position around us and move towards it. + float randomAngle=util::random(2*PI); + float randomDist=util::random(24*6); + m.target=m.GetPos()+vf2d{sin(randomAngle),cos(randomAngle)}*randomDist; + } }else if(line.length()<=24.f*ConfigInt("CloseInRange")/100.0f){ m.SetState(State::NORMAL); @@ -107,7 +115,14 @@ void Monster::STRATEGY::SHOOT_AFAR(Monster&m,float fElapsedTime,std::string stra m.canMove=movedX&&movedY; } if(!pathfindingDecision&&m.targetAcquireTimer==0){ - m.StartPathfinding(2.5); + bool pathFound=m.StartPathfinding(2.5); + if(!pathFound){ + m.SetState(State::MOVE_TOWARDS); + //Choose a random position around us and move towards it. + float randomAngle=util::random(2*PI); + float randomDist=util::random(24*6); + m.target=m.GetPos()+vf2d{sin(randomAngle),cos(randomAngle)}*randomDist; + } }else if((m.path.points.size()==0&&!m.canMove)||line.length()>=24.f*ConfigInt("Range")/100.f){ m.SetState(State::NORMAL); diff --git a/Adventures in Lestoria/SoundEffect.cpp b/Adventures in Lestoria/SoundEffect.cpp index a4f739dc..1af94d0d 100644 --- a/Adventures in Lestoria/SoundEffect.cpp +++ b/Adventures in Lestoria/SoundEffect.cpp @@ -86,7 +86,7 @@ void SoundEffect::PlaySFX(const std::string_view eventName,const vf2d&pos){ float distanceFromPlayer=geom2d::line(game->GetPlayer()->GetPos(),pos).length(); if(distanceFromPlayerGetPlayer()->GetX())/soundActivationRange; //0-1 where 1 is full volume. + float xDistRatio=(game->GetPlayer()->GetX()-pos.x)/soundActivationRange; //0-1 where 1 is full volume. float vol=distRatio*sfx.vol; float pan=xDistRatio; diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index 77e42156..f33202d1 100644 --- a/Adventures in Lestoria/Version.h +++ b/Adventures in Lestoria/Version.h @@ -39,7 +39,7 @@ All rights reserved. #define VERSION_MAJOR 0 #define VERSION_MINOR 2 #define VERSION_PATCH 1 -#define VERSION_BUILD 5682 +#define VERSION_BUILD 5724 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Adventures in Lestoria/Wizard.cpp b/Adventures in Lestoria/Wizard.cpp index ce98750a..6871e26b 100644 --- a/Adventures in Lestoria/Wizard.cpp +++ b/Adventures in Lestoria/Wizard.cpp @@ -121,11 +121,22 @@ void Wizard::InitializeClassAbilities(){ dist-=4; teleportPoint=p->GetPos()+pointTowardsMouse*dist; } - if(dist>0&&p->CanPathfindTo(p->GetPos(),teleportPoint,float("Wizard.Right Click Ability.TilesMax"_I))){ + vi2d tilePos=vi2d(teleportPoint/float(game->GetCurrentMapData().tilewidth))*game->GetCurrentMapData().tilewidth; + geom2d::rectcollisionRect=game->GetTileCollision(game->GetCurrentLevel(),teleportPoint,p->OnUpperLevel()); + #pragma region lambdas + auto NoTileCollisionExistsHere=[&](){return collisionRect.pos==game->NO_COLLISION.pos&&collisionRect.size==game->NO_COLLISION.size;}; + #pragma endregion + collisionRect.pos+=tilePos; + #pragma region lambdas + auto NoPlayerCollisionWithTile=[&](){return !geom2d::overlaps(geom2d::circle(teleportPoint,4),collisionRect);}; + #pragma endregion + if(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(); + std::cout<<"Start Position: "<<(p->teleportStartPosition)<iframe_time="Wizard.Right Click Ability.IframeTime"_F; for(int i=0;i<"Wizard.Right Click Ability.ParticleCount"_I;i++){ game->AddEffect(std::make_unique(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)); diff --git a/Adventures in Lestoria/assets/config/items/items.txt b/Adventures in Lestoria/assets/config/items/items.txt index 86694c8a..ac3cb67c 100644 --- a/Adventures in Lestoria/assets/config/items/items.txt +++ b/Adventures in Lestoria/assets/config/items/items.txt @@ -28,7 +28,7 @@ ItemDrop Item Drop Suction Range = 360 # Item drop suction strength - Item Drop Suction Strength = 5000 + Item Drop Suction Strength = 8000 # Item drop initial rise speed Item Drop Initial Rise Speed = 10 diff --git a/Adventures in Lestoria/olcUTIL_Geometry2D.h b/Adventures in Lestoria/olcUTIL_Geometry2D.h index 6a3130b9..7b23f534 100644 --- a/Adventures in Lestoria/olcUTIL_Geometry2D.h +++ b/Adventures in Lestoria/olcUTIL_Geometry2D.h @@ -311,7 +311,12 @@ namespace olc // Linearly interpolate between this vector, and another vector, given normalised parameter 't' inline constexpr v_2d lerp(const v_2d& v1, const double t) const { - return (T(1.0 - t)) + (v1 * T(t)); + return this->operator*(T(1.0 - t)) + (v1 * T(t)); + } + + inline constexpr v_2d operator * (const T& rhs) const + { + return v_2d(this->x * rhs, this->y * rhs); } // Compare if this vector is numerically equal to another