Add in map_range util function. Fix up FadeInOutEffect to still behave with its old behavior for Poison Pool while enabling new oscillating behaviors for size/color. Add in unit test for map_range. Implement Black Hole Enchant. Release Build 11250.

This commit is contained in:
sigonasr2 2024-09-04 02:15:26 -05:00
parent 94b324e7a2
commit 5b7c25df46
21 changed files with 159 additions and 23 deletions

View File

@ -1210,5 +1210,20 @@ namespace EnchantTests
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.");
}
TEST_METHOD(BlackHoleNoEnchantCheck){
Game::ChangeClass(player,WIZARD);
player->SetTestScreenAimingLocation(player->GetPos()+vf2d{16.f,0.f});
player->CheckAndPerformAbility(player->GetRightClickAbility(),testKeyboardInput);
Game::Update(0.f);
Assert::AreEqual(size_t(0),game->GetBackgroundEffects().size(),L"There should be no background effects (i.e. Black Holes).");
}
TEST_METHOD(BlackHoleEnchantCheck){
Game::ChangeClass(player,WIZARD);
Game::GiveAndEquipEnchantedRing("Black Hole");
player->SetTestScreenAimingLocation(player->GetPos()+vf2d{16.f,0.f});
player->CheckAndPerformAbility(player->GetRightClickAbility(),testKeyboardInput);
Game::Update(0.f);
Assert::AreEqual(size_t(1),game->GetBackgroundEffects().size(),L"There should be a background effect (i.e. the Black Hole).");
}
};
}

View File

@ -38,6 +38,7 @@ All rights reserved.
#include "CppUnitTest.h"
#include "AdventuresInLestoria.h"
#include "util.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
@ -105,5 +106,22 @@ namespace EngineTests
std::u32string u32middleColorCodeStr{middleColorCodeStr.begin(),middleColorCodeStr.end()};
Assert::AreEqual(WHITE.n,testGame->GetFinalRenderColor(WHITE,middleColorCodeStr).n,L"Should use source color since there's no leading HTML color code.");
}
TEST_METHOD(UtilMapRangeTest){
Assert::AreEqual(0.f,util::map_range<float>(0.f,0,100,0,100),L"0 in input range 0-100 output range 0-100 maps to 0");
Assert::AreEqual(100.f,util::map_range<float>(100.f,0,100,0,100),L"100 in input range 0-100 output range 0-100 maps to 100");
Assert::AreEqual(50.f,util::map_range<float>(50.f,0,100,0,100),L"50 in input range 0-100 output range 0-100 maps to 100");
Assert::AreEqual(0.f,util::map_range<float>(0.f,0,50,0,100),L"0 in input range 0-50 output range 0-100 maps to 0");
Assert::AreEqual(200.f,util::map_range<float>(100.f,0,50,0,100),L"100 in input range 0-50 output range 0-100 maps to 200");
Assert::AreEqual(100.f,util::map_range<float>(50.f,0,50,0,100),L"50 in input range 0-50 output range 0-100 maps to 100");
Assert::AreEqual(100.f,util::map_range<float>(0.f,0,100,100,200),L"0 in input range 0-100 output range 100-200 maps to 100");
Assert::AreEqual(200.f,util::map_range<float>(100.f,0,100,100,200),L"100 in input range 0-100 output range 100-200 maps to 200");
Assert::AreEqual(150.f,util::map_range<float>(50.f,0,100,100,200),L"50 in input range 0-100 output range 100-200 maps to 150");
Assert::AreEqual(0.f,util::map_range<float>(0.f,50,100,100,200),L"0 in input range 50-100 output range 100-200 maps to 0");
Assert::AreEqual(200.f,util::map_range<float>(100.f,50,100,100,200),L"100 in input range 50-100 output range 100-200 maps to 200");
Assert::AreEqual(100.f,util::map_range<float>(50.f,50,100,100,200),L"50 in input range 50-100 output range 100-200 maps to 100");
}
};
}

View File

@ -387,6 +387,10 @@
<SubType>
</SubType>
</ClInclude>
<ClInclude Include="BlackHole.h">
<SubType>
</SubType>
</ClInclude>
<ClInclude Include="BombBoom.h">
<SubType>
</SubType>

View File

@ -684,6 +684,9 @@
<ClInclude Include="Timer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="BlackHole.h">
<Filter>Source Files\Effects</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Player.cpp">

View File

@ -0,0 +1,58 @@
#pragma region License
/*
License (OLC-3)
~~~~~~~~~~~~~~~
Copyright 2024 Joshua Sigona <sigonasr2@gmail.com>
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions or derivations of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions or derivative works in binary form must reproduce the above
copyright notice. This list of conditions and the following disclaimer must be
reproduced in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may
be used to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
Portions of this software are copyright © 2024 The FreeType
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
All rights reserved.
*/
#pragma endregion
#pragma once
#include "AdventuresInLestoria.h"
#include "util.h"
INCLUDE_MONSTER_LIST
struct BlackHole:FadeInOutEffect{
inline BlackHole(OscillatorVf2d pos,const std::string&img,float lifetime,float cycleSpd,bool onUpperLevel,OscillatorFloat size,vf2d spd,OscillatorPixel col,float rotation,float rotationSpd,bool additiveBlending=false,float particleSpawnFreq=0.f,const std::function<Effect(const Effect&self)>&particleGenerator={})
:FadeInOutEffect(pos,img,lifetime,cycleSpd,onUpperLevel,size,spd,col,rotation,rotationSpd,additiveBlending,particleSpawnFreq,particleGenerator){}
inline bool Update(float fElapsedTime){
for(std::shared_ptr<Monster>&m:MONSTER_LIST){
float distToMonster{util::distance(pos,m->GetPos())};
if(distToMonster<="Black Hole"_ENC["PULL IN RADIUS"]/100.f*24){
float pullInForce{util::map_range<float>(distToMonster,0,"Black Hole"_ENC["PULL IN RADIUS"]/100.f*24,"Black Hole"_ENC["PULL IN FORCE MAX"],"Black Hole"_ENC["PULL IN FORCE MIN"])};
m->AddAddedVelocity(util::pointTo(m->GetPos(),pos)*pullInForce);
}
}
return FadeInOutEffect::Update(fElapsedTime);
}
};

View File

@ -119,4 +119,8 @@ const float Effect::GetZ()const{
void Effect::SetType(const EffectType type){
this->type=type;
}
const bool&Effect::OnUpperLevel()const{
return upperLevel;
}

View File

@ -45,13 +45,13 @@ class Player;
using HitList=std::unordered_set<std::variant<Monster*,Player*>>;
using OscillatorVf2d=std::pair<vf2d,vf2d>;
using OscillatorPixel=std::pair<Pixel,Pixel>;
using OscillatorFloat=std::pair<float,float>;
enum class EffectType{
NONE,
SPELL_CIRCLE,
MONSTER_SOUL,
BLINK_PORTAL,
BLACK_HOLE,
};
struct Effect{
@ -82,6 +82,7 @@ public:
bool OnUpperLevel();
const EffectType GetType()const;
const float GetZ()const;
const bool&OnUpperLevel()const;
void SetType(const EffectType type);
protected:
float original_fadeOutTime;
@ -172,23 +173,23 @@ 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={});
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(const Effect&self)>&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={});
FadeInOutEffect(OscillatorVf2d pos,const std::string&img,float lifetime,float cycleSpd,bool onUpperLevel,OscillatorFloat size,vf2d spd,OscillatorPixel col,float rotation,float rotationSpd,bool additiveBlending=false,float particleSpawnFreq=0.f,const std::function<Effect(const Effect&self)>&particleGenerator={});
virtual bool Update(float fElapsedTime)override;
virtual void Draw()const override;
std::function<Effect()>particleGenerator;
std::function<Effect(const Effect&self)>particleGenerator;
const float particleSpawnFreq;
const float cycleSpd;
const OscillatorVf2d posOscillator;
const OscillatorFloat sizeOscillator;
const OscillatorPixel colOscillator;
float particleSpawnTimer{};
const float originalParticleSpawnTimer{};
};
struct PoisonPool:FadeInOutEffect{
PoisonPool(vf2d pos,const std::string&img,float radius,int damage,float damageFreq,const HurtType friendly,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={});
PoisonPool(vf2d pos,const std::string&img,float radius,int damage,float damageFreq,const HurtType friendly,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(const Effect&self)>&particleGenerator={});
virtual bool Update(float fElapsedTime)override final;
const int damage;
float damageTimer{};

View File

@ -39,25 +39,27 @@ All rights reserved.
#include "Effect.h"
#include "AdventuresInLestoria.h"
#include "DEFINES.h"
#include "util.h"
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)
: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){}
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(const Effect&self)>&particleGenerator)
:FadeInOutEffect({pos,pos},img,lifetime,cycleSpd,onUpperLevel,{size,size},spd,{col,{col.r,col.g,col.b,0}},rotation,rotationSpd,additiveBlending,particleSpawnFreq,particleGenerator){}
FadeInOutEffect::FadeInOutEffect(OscillatorVf2d pos,const std::string&img,float lifetime,float cycleSpd,bool onUpperLevel,OscillatorFloat size,vf2d spd,OscillatorPixel col,float rotation,float rotationSpd,bool additiveBlending,float particleSpawnFreq,const std::function<Effect(const Effect&self)>&particleGenerator)
:particleSpawnFreq(particleSpawnFreq),particleGenerator(particleGenerator),cycleSpd(cycleSpd),particleSpawnTimer(particleSpawnFreq),originalParticleSpawnTimer(particleSpawnTimer),posOscillator(pos),colOscillator(col),sizeOscillator(size),Effect(pos.first,lifetime,img,onUpperLevel,size.first,0.25f,spd,col.first,rotation,rotationSpd,additiveBlending){}
bool FadeInOutEffect::Update(float fElapsedTime){
if(particleGenerator){
particleSpawnTimer-=fElapsedTime;
if(particleSpawnTimer<=0.f){
particleSpawnTimer+=originalParticleSpawnTimer;
game->AddEffect(std::make_unique<Effect>(particleGenerator()));
game->AddEffect(std::make_unique<Effect>(particleGenerator(*this)));
}
}
float t{float(abs(sin(PI*game->GetRunTime()*cycleSpd)))};
pos=posOscillator.first.lerp(posOscillator.second,t);
size={util::lerp(sizeOscillator.first,sizeOscillator.second,t),util::lerp(sizeOscillator.first,sizeOscillator.second,t)};
col=PixelLerp(colOscillator.first,colOscillator.second,t);
col.a=t*255;
col.a=util::lerp(colOscillator.first.a,colOscillator.second.a,t);
return Effect::Update(fElapsedTime);
}
void FadeInOutEffect::Draw()const{

View File

@ -77,7 +77,7 @@ public:
const std::optional<AbilitySlot>&GetAbilitySlot()const;
const std::optional<Ability*>GetAbility()const; //Get the ability this enchant is tied to.
const float GetConfigValue(const std::string_view keyName)const;
const float operator[](const std::string& name)const;
const float operator[](const std::string&name)const;
private:
class ItemEnchantCategoryData{
friend class ItemEnchantInfo;

View File

@ -314,7 +314,7 @@ bool Monster::Update(float fElapsedTime){
}
}
#pragma endregion
if(vel.x>0){
vel.x=std::max(0.f,vel.x-friction*fElapsedTime);
} else {
@ -325,10 +325,20 @@ bool Monster::Update(float fElapsedTime){
} else {
vel.y=std::min(0.f,vel.y+friction*fElapsedTime);
}
if(addedVel.x>0){
addedVel.x=std::max(0.f,addedVel.x-friction*fElapsedTime);
} else {
addedVel.x=std::min(0.f,addedVel.x+friction*fElapsedTime);
}
if(addedVel.y>0){
addedVel.y=std::max(0.f,addedVel.y-friction*fElapsedTime);
} else {
addedVel.y=std::min(0.f,addedVel.y+friction*fElapsedTime);
}
bumpedIntoTerrain=false;
if(vel!=vf2d{0,0}){
bumpedIntoTerrain|=SetX(pos.x+vel.x*fElapsedTime);
bumpedIntoTerrain|=SetY(pos.y+vel.y*fElapsedTime);
if(vel!=vf2d{0,0}||addedVel!=vf2d{0,0}){
bumpedIntoTerrain|=SetX(pos.x+vf2d{vel+addedVel}.x*fElapsedTime);
bumpedIntoTerrain|=SetY(pos.y+vf2d{vel+addedVel}.y*fElapsedTime);
}
if(IsAlive()){
@ -1610,4 +1620,7 @@ const bool Monster::FaceTarget()const{
}
void Monster::ResetCurseOfDeathDamage(){
accumulatedCurseOfDeathDamage=0;
}
void Monster::AddAddedVelocity(vf2d vel){
this->addedVel+=vel;
}

View File

@ -110,6 +110,7 @@ public:
void Collision(Monster&p);
void Collision();
void SetVelocity(vf2d vel);
void AddAddedVelocity(vf2d vel); //NOTE: If a monster is trying to set its velocity internally, use SetVelocity() instead. This function is for external sources affecting this monster's velocity.
//Returns false if the monster could not be moved to the requested location due to collision.
bool SetPos(vf2d pos);
//Returns false if the monster could not be moved to the requested location due to collision.
@ -315,6 +316,7 @@ private:
void LongLastingMarkEffect(float&out_markDuration); //Modifies a given duration.
float stunTimer{};
int accumulatedCurseOfDeathDamage{};
vf2d addedVel{};
struct STRATEGY{
static std::string ERR;

View File

@ -72,7 +72,7 @@ void PoisonBottle::Update(float fElapsedTime){
game->AddEffect(std::make_unique<Effect>(pos+vf2d{util::random(16)*poisonCircleScale,util::random(2*PI)}.cart(),util::random_range(1.f,4.f),"circle.png",game->GetPlayer()->OnUpperLevel(),vf2d{size,size},util::random_range(0.2f,0.5f),vf2d{util::random_range(-6.f,6.f),util::random_range(-12.f,-4.f)},col));
}
if(additionalBounceCount==0&&game->GetPlayer()->HasEnchant("Pooling Poison")){
game->AddEffect(std::make_unique<PoisonPool>(pos,"poison_pool.png",bounceExplodeRadius,game->GetPlayer()->GetAttack()*"Pooling Poison"_ENC["POISON POOL DAMAGE PCT"]/100.f,"Pooling Poison"_ENC["POISON POOL DAMAGE FREQUENCY"],friendly?HurtType::MONSTER:HurtType::PLAYER,"Pooling Poison"_ENC["SPLASH LINGER TIME"],0.5f,OnUpperLevel(),poisonCircleScale,vf2d{},WHITE,0.f,0.f,false,0.05f,[pos=pos,col=col,poisonCircleScale](){
game->AddEffect(std::make_unique<PoisonPool>(pos,"poison_pool.png",bounceExplodeRadius,game->GetPlayer()->GetAttack()*"Pooling Poison"_ENC["POISON POOL DAMAGE PCT"]/100.f,"Pooling Poison"_ENC["POISON POOL DAMAGE FREQUENCY"],friendly?HurtType::MONSTER:HurtType::PLAYER,"Pooling Poison"_ENC["SPLASH LINGER TIME"],0.5f,OnUpperLevel(),poisonCircleScale,vf2d{},WHITE,0.f,0.f,false,0.05f,[pos=pos,col=col,poisonCircleScale](const Effect&self){
float size{util::random_range(0.4f,0.8f)};
return Effect{pos+vf2d{util::random(16)*poisonCircleScale,util::random(2*PI)}.cart(),util::random_range(1.f,4.f),"circle.png",game->GetPlayer()->OnUpperLevel(),vf2d{size,size},util::random_range(0.2f,0.5f),vf2d{util::random_range(-6.f,6.f),util::random_range(-12.f,-4.f)},col};
}),true);

View File

@ -42,7 +42,7 @@ All rights reserved.
INCLUDE_game
PoisonPool::PoisonPool(vf2d pos,const std::string&img,float radius,int damage,float damageFreq,const HurtType friendly,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)
PoisonPool::PoisonPool(vf2d pos,const std::string&img,float radius,int damage,float damageFreq,const HurtType friendly,float lifetime,float cycleSpd,bool onUpperLevel,float size,vf2d spd,Pixel col,float rotation,float rotationSpd,bool additiveBlending,float particleSpawnFreq,const std::function<Effect(const Effect&self)>&particleGenerator)
:damage(damage),damageTimer(damageFreq),originalDamageTimer(damageTimer),radius(radius),friendly(friendly),poisonPoolSFXID(SoundEffect::PlayLoopingSFX("Poison Pool",pos)),FadeInOutEffect(pos,img,lifetime,cycleSpd,onUpperLevel,size,spd,col,rotation,rotationSpd,additiveBlending,particleSpawnFreq,particleGenerator){}
bool PoisonPool::Update(float fElapsedTime){

View File

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

View File

@ -44,6 +44,7 @@ All rights reserved.
#include "config.h"
#include "util.h"
#include "SoundEffect.h"
#include "BlackHole.h"
INCLUDE_MONSTER_LIST
INCLUDE_BULLET_LIST
@ -155,11 +156,19 @@ void Wizard::InitializeClassAbilities(){
if(game->TestingModeEnabled()||dist>0&&p->CanPathfindTo(p->GetPos(),teleportPoint,float("Wizard.Right Click Ability.TilesMax"_I))
&&(NoTileCollisionExistsHere()||NoPlayerCollisionWithTile())){
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)};
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(),OscillatorFloat{0.9f,1.1f},vf2d{},OscillatorPixel{WHITE,0x50196f},0.f,0.f),true)};
eff.SetType(EffectType::BLINK_PORTAL);
}
TeleportTo(teleportPoint);
p->lastPathfindingCooldown=0.1f;
if(p->HasEnchant("Black Hole")){
Effect&blackHoleEff{game->AddEffect(std::make_unique<BlackHole>(OscillatorVf2d{p->GetPos(),p->GetPos()+vf2d{0,-6.f}},"blackhole.png","Black Hole"_ENC["BLACK HOLE DURATION"],0.75f,p->OnUpperLevel(),OscillatorFloat{3.4f,3.7f},vf2d{},OscillatorPixel{WHITE,WHITE},util::random(2*PI),PI/3,false,0.03f,[](const Effect&self){
vf2d particlePos{self.pos+vf2d{"Black Hole"_ENC["PULL IN RADIUS"]/100.f*24,util::random(2*PI)}.cart()};
return Effect{particlePos,util::random_range(0.3f,0.5f),"pixel.png",self.OnUpperLevel(),util::random(2.f),0.1f,util::pointTo(particlePos,self.pos)*util::random_range(700,1000),PixelLerp(BLACK,Pixel(0x9859de),util::random(1.f)),0.f,0.f,false};
}),true)};
}
return true;
} else {
p->NotificationDisplay("Cannot Teleport to that location!",0.5f);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 983 B

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -495,6 +495,9 @@ Item Enchants
Affects = Right Click Ability
BLACK HOLE DURATION = 4s
PULL IN FORCE MIN = 1
PULL IN FORCE MAX = 6
PULL IN RADIUS = 350
# Stat, Lowest, Highest Value
# Stat Modifier[0] = ..., 0, 0

View File

@ -216,5 +216,4 @@ void util::turn_towards_direction(float&angle,float target,float rate)
std::wstring util::to_wstring(const std::string&str){
return {str.begin(),str.end()};
}
}

View File

@ -73,6 +73,11 @@ namespace olc::util{
std::wstring wformat(std::string str,_Args&..._Vals){
return util::to_wstring(std::vformat(str,std::make_format_args(_Vals...)));
}
template<class T>
T map_range(T x, T in_min, T in_max, T out_min, T out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
}
template<class TL, class TR>