Fix bug with double rendering. Not using iterator marker to determine what else to draw. Fix bug with maximum health not healing to maximum when health is affected by Health %. Refactored wind speed to be a global value within the game's engine. Included speed reduction properties for wind when warrior blocks. Include projectiles/player being affected by wind and casting to be allowed when pushed by wind. Release Build 9507.
This commit is contained in:
parent
25a2879929
commit
46ee54d7c5
@ -1403,15 +1403,19 @@ void AiL::RenderWorld(float fElapsedTime){
|
||||
}
|
||||
#pragma endregion
|
||||
#pragma region Remaining Rendering
|
||||
for(Monster*m:monstersBeforeLower){
|
||||
while(monstersBeforeLowerIt!=monstersBeforeLower.end()){
|
||||
Monster*const m=*monstersBeforeLowerIt;
|
||||
m->strategyDraw(this,*m,MONSTER_DATA[m->GetName()].GetAIStrategy());
|
||||
m->Draw();
|
||||
++monstersBeforeLowerIt;
|
||||
}
|
||||
for(const Effect*const e:backgroundEffectsLower){
|
||||
e->Draw();
|
||||
}
|
||||
for(const int dropInd:dropsBeforeLower){
|
||||
while(dropsBeforeLowerIt!=dropsBeforeLower.end()){
|
||||
const int dropInd=*dropsBeforeLowerIt;
|
||||
ItemDrop::drops[dropInd].Draw();
|
||||
++dropsBeforeLowerIt;
|
||||
}
|
||||
if(!player->rendered&&!player->upperLevel){
|
||||
player->rendered=true;
|
||||
@ -1421,11 +1425,14 @@ void AiL::RenderWorld(float fElapsedTime){
|
||||
}
|
||||
RenderPlayer(player->GetPos(),{1,1});
|
||||
}
|
||||
for(Monster* m:monstersAfterLower){
|
||||
while(monstersAfterLowerIt!=monstersAfterLower.end()){
|
||||
Monster*const m=*monstersAfterLowerIt;
|
||||
m->strategyDraw(this,*m,MONSTER_DATA[m->GetName()].GetAIStrategy());
|
||||
m->Draw();
|
||||
++monstersAfterLowerIt;
|
||||
}
|
||||
for(const int dropInd:dropsAfterLower){
|
||||
while(dropsAfterLowerIt!=dropsAfterLower.end()){
|
||||
const int dropInd=*dropsAfterLowerIt;
|
||||
ItemDrop::drops[dropInd].Draw();
|
||||
}
|
||||
for(const Bullet*const b:bulletsLower){
|
||||
@ -1697,14 +1704,17 @@ void AiL::RenderWorld(float fElapsedTime){
|
||||
}
|
||||
#pragma endregion
|
||||
#pragma region Remaining Upper Rendering
|
||||
for(Monster*m:monstersBeforeUpper){
|
||||
while(monstersBeforeUpperIt!=monstersBeforeUpper.end()){
|
||||
Monster*const m=*monstersBeforeUpperIt;
|
||||
m->strategyDraw(this,*m,MONSTER_DATA[m->GetName()].GetAIStrategy());
|
||||
m->Draw();
|
||||
++monstersBeforeUpperIt;
|
||||
}
|
||||
for(const Effect*const e:backgroundEffectsUpper){
|
||||
e->Draw();
|
||||
}
|
||||
for(const int dropInd:dropsBeforeUpper){
|
||||
while(dropsBeforeUpperIt!=dropsBeforeUpper.end()){
|
||||
const int dropInd=*dropsBeforeUpperIt;
|
||||
ItemDrop::drops[dropInd].Draw();
|
||||
}
|
||||
if(!player->rendered&&player->upperLevel){
|
||||
@ -1715,12 +1725,16 @@ void AiL::RenderWorld(float fElapsedTime){
|
||||
}
|
||||
RenderPlayer(player->GetPos(),{1,1});
|
||||
}
|
||||
for(Monster*m:monstersAfterUpper){
|
||||
while(monstersAfterUpperIt!=monstersAfterUpper.end()){
|
||||
Monster*const m=*monstersAfterUpperIt;
|
||||
m->strategyDraw(this,*m,MONSTER_DATA[m->GetName()].GetAIStrategy());
|
||||
m->Draw();
|
||||
++monstersAfterUpperIt;
|
||||
}
|
||||
for(const int dropInd:dropsAfterUpper){
|
||||
while(dropsAfterUpperIt!=dropsAfterUpper.end()){
|
||||
const int dropInd=*dropsAfterUpperIt;
|
||||
ItemDrop::drops[dropInd].Draw();
|
||||
++dropsAfterUpperIt;
|
||||
}
|
||||
for(const Bullet*const b:bulletsUpper){
|
||||
b->Draw();
|
||||
@ -2285,6 +2299,7 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
|
||||
totalDamageDealt=0;
|
||||
encounterStarted=false;
|
||||
totalBossEncounterMobs=0;
|
||||
SetWindSpeed({});
|
||||
Inventory::Clear("Monster Loot");
|
||||
Inventory::Clear("Stage Loot");
|
||||
Inventory::ResetLoadoutItemsUsed();
|
||||
@ -4274,3 +4289,10 @@ Overlay&AiL::GetOverlay(){
|
||||
void AiL::SetOverlay(std::string animationName,Pixel overlayCol){
|
||||
hudOverlay=Overlay{animationName,overlayCol};
|
||||
}
|
||||
|
||||
void AiL::SetWindSpeed(vf2d newWindSpd){
|
||||
windSpd=newWindSpd;
|
||||
}
|
||||
const vf2d&AiL::GetWindSpeed()const{
|
||||
return windSpd;
|
||||
}
|
@ -196,6 +196,7 @@ private:
|
||||
float vignetteDisplayTime=0.f;
|
||||
bool savingFile=false;
|
||||
bool prevStageCompleted=false;
|
||||
vf2d windSpd{};
|
||||
|
||||
void ValidateGameStatus();
|
||||
void _PrepareLevel(MapName map,MusicChange changeMusic);
|
||||
@ -351,6 +352,8 @@ public:
|
||||
void SetBossIndicatorPos(const vf2d pos);
|
||||
void SetOverlay(std::string animationName,Pixel overlayCol);
|
||||
Overlay&GetOverlay();
|
||||
void SetWindSpeed(vf2d newWindSpd);
|
||||
const vf2d&GetWindSpeed()const;
|
||||
|
||||
struct TileGroupData{
|
||||
vi2d tilePos;
|
||||
|
@ -139,6 +139,7 @@ void Bullet::_Update(const float fElapsedTime){
|
||||
}else{
|
||||
pos+=vel*fElapsedTime;
|
||||
}
|
||||
if(IsPlayerAutoAttackProjectile()){pos+=game->GetWindSpeed()*game->GetElapsedTime();}
|
||||
if(/*World size in PIXELS!*/vi2d worldSize=game->GetCurrentMapData().MapSize*game->GetCurrentMapData().TileSize;pos.x+radius<-WINDOW_SIZE.x||pos.x-radius>worldSize.x+WINDOW_SIZE.x||pos.y+radius<-WINDOW_SIZE.y||pos.y-radius>worldSize.y+WINDOW_SIZE.y){
|
||||
dead=true;
|
||||
return;
|
||||
@ -225,5 +226,5 @@ const bool Bullet::IsPlayerAutoAttackProjectile()const{
|
||||
}
|
||||
|
||||
void Bullet::AddVelocity(vf2d vel){
|
||||
this->vel+=vel;
|
||||
this->vel+=vel*game->GetElapsedTime();
|
||||
}
|
@ -440,7 +440,7 @@ void Monster::Draw()const{
|
||||
|
||||
if(GetZ()>0){
|
||||
vf2d shadowScale=vf2d{8*GetSizeMult()/3.f,1}/std::max(1.f,GetZ()/24);
|
||||
game->view.DrawDecal(drawPos-vf2d{3,3}*shadowScale/2+vf2d{0,6*GetSizeMult()},GFX["circle.png"].Decal(),shadowScale,BLACK);
|
||||
game->view.DrawDecal(GetPos()+hitTimerOffset-vf2d{3,3}*shadowScale/2+vf2d{0,6*GetSizeMult()},GFX["circle.png"].Decal(),shadowScale,BLACK);
|
||||
}
|
||||
|
||||
const bool NotOnTitleScreen=GameState::STATE!=GameState::states[States::MAIN_MENU];
|
||||
|
@ -143,7 +143,7 @@ void Player::ForceSetPos(vf2d pos){
|
||||
Moved();
|
||||
}
|
||||
|
||||
bool Player::_SetX(float x,const bool playerInvoked){
|
||||
bool Player::_SetX(float x,MoveFlag::MoveFlag flags,const bool playerInvoked){
|
||||
vf2d newPos={x,pos.y};
|
||||
vi2d tilePos=vi2d(newPos/float(game->GetCurrentMapData().tilewidth))*game->GetCurrentMapData().tilewidth;
|
||||
geom2d::rect<float>collisionRect=game->GetTileCollision(game->GetCurrentLevel(),newPos,upperLevel);
|
||||
@ -152,7 +152,7 @@ bool Player::_SetX(float x,const bool playerInvoked){
|
||||
#pragma endregion
|
||||
if(NoTileCollisionExistsHere()){
|
||||
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();
|
||||
Moved(flags);
|
||||
return true;
|
||||
} else {
|
||||
geom2d::rect<float>collision={collisionRect.pos,collisionRect.size};
|
||||
@ -162,21 +162,21 @@ bool Player::_SetX(float x,const bool playerInvoked){
|
||||
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();
|
||||
Moved(flags);
|
||||
return true;
|
||||
}else
|
||||
if(playerInvoked){ //If player invoked, we'll try the smart move system.
|
||||
vf2d pushDir=geom2d::line<float>(collision.middle(),pos).vector().norm();
|
||||
newPos={newPos.x,pos.y+pushDir.y*12};
|
||||
if(NoPlayerCollisionWithTile()){
|
||||
return _SetY(pos.y+pushDir.y*game->GetElapsedTime()*12,false);
|
||||
return _SetY(pos.y+pushDir.y*game->GetElapsedTime()*12,flags,false);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
bool Player::_SetY(float y,const bool playerInvoked){
|
||||
bool Player::_SetY(float y,MoveFlag::MoveFlag flags,const bool playerInvoked){
|
||||
vf2d newPos={pos.x,y};
|
||||
vi2d tilePos=vi2d(newPos/float(game->GetCurrentMapData().tilewidth))*game->GetCurrentMapData().tilewidth;
|
||||
geom2d::rect<float>collisionRect=game->GetTileCollision(game->GetCurrentLevel(),newPos,upperLevel);
|
||||
@ -185,7 +185,7 @@ bool Player::_SetY(float y,const bool playerInvoked){
|
||||
#pragma endregion
|
||||
if(NoTileCollisionExistsHere()){
|
||||
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();
|
||||
Moved(flags);
|
||||
return true;
|
||||
} else {
|
||||
geom2d::rect<float>collision={collisionRect.pos,collisionRect.size};
|
||||
@ -195,37 +195,37 @@ bool Player::_SetY(float y,const bool playerInvoked){
|
||||
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();
|
||||
Moved(flags);
|
||||
return true;
|
||||
}else
|
||||
if(playerInvoked){ //If player invoked, we'll try the smart move system.{
|
||||
vf2d pushDir=geom2d::line<float>(collision.middle(),pos).vector().norm();
|
||||
newPos={pos.x+pushDir.x*12,newPos.y};
|
||||
if(NoPlayerCollisionWithTile()){
|
||||
return _SetX(pos.x+pushDir.x*game->GetElapsedTime()*12,false);
|
||||
return _SetX(pos.x+pushDir.x*game->GetElapsedTime()*12,flags,false);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Player::SetX(float x){
|
||||
return _SetX(x);
|
||||
bool Player::SetX(float x,MoveFlag::MoveFlag flags){
|
||||
return _SetX(x,flags);
|
||||
}
|
||||
|
||||
bool Player::SetY(float y){
|
||||
return _SetY(y);
|
||||
bool Player::SetY(float y,MoveFlag::MoveFlag flags){
|
||||
return _SetY(y,flags);
|
||||
}
|
||||
|
||||
void Player::SetZ(float z){
|
||||
this->z=z;
|
||||
}
|
||||
|
||||
bool Player::SetPos(vf2d pos){
|
||||
bool resultX=SetX(pos.x);
|
||||
bool resultY=SetY(pos.y);
|
||||
bool Player::SetPos(vf2d pos,MoveFlag::MoveFlag flags){
|
||||
bool resultX=SetX(pos.x,flags);
|
||||
bool resultY=SetY(pos.y,flags);
|
||||
if(resultY&&!resultX){
|
||||
resultX=SetX(pos.x);
|
||||
resultX=SetX(pos.x,flags);
|
||||
}
|
||||
return resultX||resultY;
|
||||
}
|
||||
@ -548,6 +548,12 @@ void Player::Update(float fElapsedTime){
|
||||
ERR(std::format("WARNING! The velocity vector for the player is NOT normal! Current vel:{} . Attempting manual resetting of velocity.",vel.str()));
|
||||
vel={};
|
||||
}
|
||||
|
||||
vf2d finalWindSpd=game->GetWindSpeed();
|
||||
if(GetState()==State::BLOCK)finalWindSpd*=1-("Warrior.Right Click Ability.Knockback Reduction"_F/100.f);
|
||||
|
||||
game->GetPlayer()->SetPos(game->GetPlayer()->GetPos()+finalWindSpd*game->GetElapsedTime(),MoveFlag::PREVENT_CAST_CANCELLING);
|
||||
|
||||
if(vel!=vf2d{0,0}){
|
||||
float newX=pos.x+vel.x*fElapsedTime;
|
||||
float newY=pos.y+vel.y*fElapsedTime;
|
||||
@ -875,8 +881,8 @@ void Player::CancelCast(){
|
||||
}
|
||||
}
|
||||
|
||||
void Player::Moved(){
|
||||
if(state==State::CASTING){
|
||||
void Player::Moved(MoveFlag::MoveFlag flags){
|
||||
if(!(flags&MoveFlag::PREVENT_CAST_CANCELLING)&&state==State::CASTING){
|
||||
state=State::NORMAL;
|
||||
castPrepAbility->waitForRelease=true;
|
||||
CancelCast();
|
||||
@ -1078,7 +1084,7 @@ void Player::_SetIframes(float duration){
|
||||
}
|
||||
|
||||
bool Player::Heal(int damage,bool suppressDamageNumber){
|
||||
hp=std::clamp(hp+damage,0,int(GetStat("Health")));
|
||||
hp=std::clamp(hp+damage,0,int(GetMaxHealth()));
|
||||
if(!suppressDamageNumber&&damage>0){
|
||||
DAMAGENUMBER_LIST.push_back(std::make_shared<DamageNumber>(GetPos(),damage,true,HEALTH_GAIN));
|
||||
}
|
||||
@ -1577,5 +1583,5 @@ void Player::ProximityKnockback(const vf2d centerPoint,const float knockbackFact
|
||||
}
|
||||
|
||||
void Player::AddVelocity(vf2d vel){
|
||||
this->vel+=vel;
|
||||
this->vel+=vel*game->GetElapsedTime();
|
||||
}
|
@ -62,6 +62,13 @@ struct CastInfo{
|
||||
vf2d castPos{};
|
||||
};
|
||||
|
||||
namespace MoveFlag{
|
||||
enum MoveFlag{
|
||||
NONE = 0b0,
|
||||
PREVENT_CAST_CANCELLING = 0b1,
|
||||
};
|
||||
};
|
||||
|
||||
class EntityStats{
|
||||
friend class Inventory;
|
||||
ItemAttributable equipStats; //The stats after gear calculations are applied.
|
||||
@ -148,12 +155,12 @@ public:
|
||||
void RestoreMana(int amt,bool suppressDamageNumber=false);
|
||||
void ConsumeMana(int amt);
|
||||
//Returns true if the move was valid and successful.
|
||||
bool SetX(float x);
|
||||
bool SetX(float x,MoveFlag::MoveFlag flags=MoveFlag::NONE);
|
||||
//Returns true if the move was valid and successful.
|
||||
bool SetY(float y);
|
||||
bool SetY(float y,MoveFlag::MoveFlag flags=MoveFlag::NONE);
|
||||
void SetZ(float z);
|
||||
//Returns true if the move was valid and successful.
|
||||
bool SetPos(vf2d pos);
|
||||
bool SetPos(vf2d pos,MoveFlag::MoveFlag flags=MoveFlag::NONE);
|
||||
//Ignores collision checking and sets the player at the given position.
|
||||
void ForceSetPos(vf2d pos);
|
||||
void SetState(State::State newState);
|
||||
@ -189,7 +196,7 @@ public:
|
||||
bool IsOutOfCombat();
|
||||
float GetEndZoneStandTime();
|
||||
//Triggers when the player has moved.
|
||||
void Moved();
|
||||
void Moved(MoveFlag::MoveFlag flags=MoveFlag::NONE);
|
||||
virtual ~Player()=default;
|
||||
virtual Class GetClass()=0;
|
||||
virtual bool AutoAttack()=0;
|
||||
@ -311,12 +318,12 @@ private:
|
||||
//If playerInvoked is true, this means the player was the one that instantiated this input, and it's not an extra movement done via collision.
|
||||
//Set playerInvoked to false when you don't want a movement loop due to collisions.
|
||||
//Typical usage is playerInvoked is true on first call, and playerInvoked is false on all subsequent chained calls.
|
||||
bool _SetX(float x,const bool playerInvoked=true);
|
||||
bool _SetX(float x,MoveFlag::MoveFlag flags=MoveFlag::NONE,const bool playerInvoked=true);
|
||||
//Returns true if the move was valid and successful.
|
||||
//If playerInvoked is true, this means the player was the one that instantiated this input, and it's not an extra movement done via collision.
|
||||
//Set playerInvoked to false when you don't want a movement loop due to collisions.
|
||||
//Typical usage is playerInvoked is true on first call, and playerInvoked is false on all subsequent chained calls.
|
||||
bool _SetY(float y,const bool playerInvoked=true);
|
||||
bool _SetY(float y,MoveFlag::MoveFlag flags=MoveFlag::NONE,const bool playerInvoked=true);
|
||||
const bool UsingAutoAim()const;
|
||||
void InitializeMinimapImage();
|
||||
bool lowHealthSoundPlayed=false;
|
||||
|
@ -23,4 +23,5 @@ New Monster Sound Effects
|
||||
|
||||
DEMO
|
||||
====
|
||||
Health % max health healing bug
|
||||
Go back and apply new rendering code.
|
@ -39,7 +39,7 @@ All rights reserved.
|
||||
#define VERSION_MAJOR 1
|
||||
#define VERSION_MINOR 2
|
||||
#define VERSION_PATCH 3
|
||||
#define VERSION_BUILD 9497
|
||||
#define VERSION_BUILD 9507
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
@ -256,10 +256,8 @@ void Monster::STRATEGY::ZEPHY(Monster&m,float fElapsedTime,std::string strategy)
|
||||
|
||||
vf2d windSpd={m.F(A::WIND_STRENGTH)*"Player.MoveSpd"_F,0.f}; //Assume we landed left and causing a wind attack to the right.
|
||||
if(!LeftLandingSite)windSpd*=-1;
|
||||
game->GetPlayer()->AddVelocity(windSpd);
|
||||
game->SetWindSpeed(windSpd);
|
||||
m.F(A::CASTING_TIMER)=ConfigFloat("Wind Attack.Wind Duration");
|
||||
|
||||
std::for_each(BULLET_LIST.begin(),BULLET_LIST.end(),[&](const std::unique_ptr<Bullet>&bullet){if(bullet->IsPlayerAutoAttackProjectile()){bullet->AddVelocity(windSpd);}});
|
||||
#pragma endregion
|
||||
|
||||
if(m.F(A::CASTING_TIMER)<=0.f){
|
||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user