Add previous player position variable and getter for the player. Add in other cannon pattern types to rotation.

Update rendering loop to use ranges and views instead of copies into vectors. Release Build 11997.
master
sigonasr2 4 days ago
parent 27bfd8e1d4
commit 6c5648bac9
  1. 183
      Adventures in Lestoria/AdventuresInLestoria.cpp
  2. 5
      Adventures in Lestoria/AdventuresInLestoria.h
  3. 42
      Adventures in Lestoria/GhostOfPirateCaptain.cpp
  4. 2
      Adventures in Lestoria/ItemDrop.cpp
  5. 2
      Adventures in Lestoria/ItemDrop.h
  6. 4
      Adventures in Lestoria/MonsterAttribute.h
  7. 8
      Adventures in Lestoria/Player.cpp
  8. 2
      Adventures in Lestoria/Player.h
  9. 2
      Adventures in Lestoria/Version.h
  10. BIN
      x64/Release/Adventures in Lestoria.exe

@ -950,99 +950,17 @@ void AiL::ProximityKnockback(const vf2d pos,const float radius,const float knock
}
void AiL::PopulateRenderLists(){
monstersBeforeLower.clear();
monstersAfterLower.clear();
monstersBeforeUpper.clear();
monstersAfterUpper.clear();
bulletsLower.clear();
bulletsUpper.clear();
backgroundEffectsLower.clear();
backgroundEffectsUpper.clear();
foregroundEffectsLower.clear();
foregroundEffectsUpper.clear();
endZones.clear();
upperEndZones.clear();
dropsBeforeLower.clear();
dropsAfterLower.clear();
dropsBeforeUpper.clear();
dropsAfterUpper.clear();
tilesWithCollision.clear();
tilesWithoutCollision.clear();
Player*pl=GetPlayer();
pl->rendered=false;
std::sort(MONSTER_LIST.begin(),MONSTER_LIST.end(),[](std::shared_ptr<Monster>&m1,std::shared_ptr<Monster>&m2){return m1->GetPos().y<m2->GetPos().y;});
std::sort(ItemDrop::drops.begin(),ItemDrop::drops.end(),[](ItemDrop&id1,ItemDrop&id2){return id1.GetPos().y<id2.GetPos().y;});
std::sort(BULLET_LIST.begin(),BULLET_LIST.end(),[](std::unique_ptr<IBullet>&b1,std::unique_ptr<IBullet>&b2){return b1->pos.y<b2->pos.y;});
std::sort(foregroundEffects.begin(),foregroundEffects.end(),[](std::unique_ptr<Effect>&e1,std::unique_ptr<Effect>&e2){return e1->pos.y<e2->pos.y;});
std::sort(backgroundEffects.begin(),backgroundEffects.end(),[](std::unique_ptr<Effect>&e1,std::unique_ptr<Effect>&e2){return e1->pos.y<e2->pos.y;});
for(auto it=MONSTER_LIST.begin();it!=MONSTER_LIST.end();++it){
Monster&m=**it;
if(m.GetPos().y<pl->GetPos().y){//This monster renders before the player does (behind the player)
if(m.OnUpperLevel()){
monstersBeforeUpper.push_back(&m);
}else{
monstersBeforeLower.push_back(&m);
}
} else {//This monster renders after the player does (in front of the player)
if(m.OnUpperLevel()){
monstersAfterUpper.push_back(&m);
}else{
monstersAfterLower.push_back(&m);
}
}
}
for(int i=0;i<ItemDrop::drops.size();i++){
ItemDrop&drop=ItemDrop::drops[i];
if(drop.GetPos().y<pl->GetPos().y){//This item drop renders before the player does (behind the player)
if(drop.OnUpperLevel()){
dropsBeforeUpper.push_back(i);
}else{
dropsBeforeLower.push_back(i);
}
} else {//This item drop renders after the player does (in front of the player)
if(drop.OnUpperLevel()){
dropsAfterUpper.push_back(i);
}else{
dropsAfterLower.push_back(i);
}
}
}
for(auto it=BULLET_LIST.begin();it!=BULLET_LIST.end();++it){
IBullet*b=(*it).get();
if(b->OnUpperLevel()){
bulletsUpper.push_back(b);
}else{
bulletsLower.push_back(b);
}
}
for(auto it=foregroundEffects.begin();it!=foregroundEffects.end();++it){
Effect*e=(*it).get();
if(e->OnUpperLevel()){
foregroundEffectsUpper.push_back(e);
}else{
foregroundEffectsLower.push_back(e);
}
}
for(auto it=backgroundEffects.begin();it!=backgroundEffects.end();++it){
Effect*e=(*it).get();
if(e->OnUpperLevel()){
backgroundEffectsUpper.push_back(e);
}else{
backgroundEffectsLower.push_back(e);
}
}
for(const ZoneData&zone:GetZones().at("EndZone")){
if(zone.isUpper){
upperEndZones.push_back(zone);
}else{
endZones.push_back(zone);
}
}
std::ranges::sort(MONSTER_LIST,[](std::shared_ptr<Monster>&m1,std::shared_ptr<Monster>&m2){return m1->GetPos().y<m2->GetPos().y;});
std::ranges::sort(ItemDrop::drops,[](ItemDrop&id1,ItemDrop&id2){return id1.GetPos().y<id2.GetPos().y;});
std::ranges::sort(BULLET_LIST,[](std::unique_ptr<IBullet>&b1,std::unique_ptr<IBullet>&b2){return b1->pos.y<b2->pos.y;});
std::ranges::sort(foregroundEffects,[](std::unique_ptr<Effect>&e1,std::unique_ptr<Effect>&e2){return e1->pos.y<e2->pos.y;});
std::ranges::sort(backgroundEffects,[](std::unique_ptr<Effect>&e1,std::unique_ptr<Effect>&e2){return e1->pos.y<e2->pos.y;});
}
void AiL::RenderTile(vi2d pos,TilesheetData tileSheet,int tileSheetIndex,vi2d tileSheetPos){
@ -1107,6 +1025,25 @@ void AiL::RenderWorld(float fElapsedTime){
PopulateRenderLists();
#pragma region Populate Render Lists
auto monstersBeforeUpper{MONSTER_LIST|std::views::filter([&pl](const std::shared_ptr<Monster>&m){return m->GetPos().y<pl->GetPos().y&&m->OnUpperLevel();})};
auto monstersBeforeLower{MONSTER_LIST|std::views::filter([&pl](const std::shared_ptr<Monster>&m){return m->GetPos().y<pl->GetPos().y&&!m->OnUpperLevel();})};
auto monstersAfterUpper{MONSTER_LIST|std::views::filter([&pl](const std::shared_ptr<Monster>&m){return m->GetPos().y>=pl->GetPos().y&&m->OnUpperLevel();})};
auto monstersAfterLower{MONSTER_LIST|std::views::filter([&pl](const std::shared_ptr<Monster>&m){return m->GetPos().y>=pl->GetPos().y&&!m->OnUpperLevel();})};
auto dropsBeforeUpper{ItemDrop::drops|std::views::filter([&pl](const ItemDrop&drop){return drop.GetPos().y<pl->GetPos().y&&drop.OnUpperLevel();})};
auto dropsBeforeLower{ItemDrop::drops|std::views::filter([&pl](const ItemDrop&drop){return drop.GetPos().y<pl->GetPos().y&&!drop.OnUpperLevel();})};
auto dropsAfterUpper{ItemDrop::drops|std::views::filter([&pl](const ItemDrop&drop){return drop.GetPos().y>=pl->GetPos().y&&drop.OnUpperLevel();})};
auto dropsAfterLower{ItemDrop::drops|std::views::filter([&pl](const ItemDrop&drop){return drop.GetPos().y>=pl->GetPos().y&&!drop.OnUpperLevel();})};
auto bulletsUpper{BULLET_LIST|std::views::filter([](const std::unique_ptr<IBullet>&bullet){return bullet->OnUpperLevel();})};
auto bulletsLower{BULLET_LIST|std::views::filter([](const std::unique_ptr<IBullet>&bullet){return !bullet->OnUpperLevel();})};
auto foregroundEffectsUpper{foregroundEffects|std::views::filter([](const std::unique_ptr<Effect>&effect){return effect->OnUpperLevel();})};
auto foregroundEffectsLower{foregroundEffects|std::views::filter([](const std::unique_ptr<Effect>&effect){return !effect->OnUpperLevel();})};
auto backgroundEffectsUpper{backgroundEffects|std::views::filter([](const std::unique_ptr<Effect>&effect){return effect->OnUpperLevel();})};
auto backgroundEffectsLower{backgroundEffects|std::views::filter([](const std::unique_ptr<Effect>&effect){return !effect->OnUpperLevel();})};
auto upperEndZones{ZONE_LIST["EndZone"]|std::views::filter([](const ZoneData&zone){return zone.isUpper;})};
auto endZones{ZONE_LIST["EndZone"]|std::views::filter([](const ZoneData&zone){return !zone.isUpper;})};
#pragma endregion
auto RenderPlayer=[&](vf2d pos,vf2d scale){
if(player->IsInvisible())return;
vf2d playerScale=vf2d(player->GetSizeMult(),player->GetSizeMult());
@ -1458,7 +1395,7 @@ void AiL::RenderWorld(float fElapsedTime){
break;
}
while(dropsBeforeLowerIt!=dropsBeforeLower.end()){
const ItemDrop&drop=ItemDrop::drops[*dropsBeforeLowerIt];
const ItemDrop&drop{*dropsBeforeLowerIt};
if(drop.pos.y<topTileY){
drop.Draw();
++dropsBeforeLowerIt;
@ -1474,7 +1411,7 @@ void AiL::RenderWorld(float fElapsedTime){
++monstersBeforeLowerIt;
}
while(dropsBeforeLowerIt!=dropsBeforeLower.end()){
const ItemDrop&drop=ItemDrop::drops[*dropsBeforeLowerIt];
const ItemDrop&drop{*dropsBeforeLowerIt};
drop.Draw();
++dropsBeforeLowerIt;
}
@ -1497,7 +1434,7 @@ void AiL::RenderWorld(float fElapsedTime){
break;
}
while(dropsAfterLowerIt!=dropsAfterLower.end()){
const ItemDrop&drop=ItemDrop::drops[*dropsAfterLowerIt];
const ItemDrop&drop{*dropsAfterLowerIt};
if(drop.pos.y<topTileY){
drop.Draw();
++dropsAfterLowerIt;
@ -1519,7 +1456,7 @@ void AiL::RenderWorld(float fElapsedTime){
++monstersBeforeLowerIt;
}
while(dropsBeforeLowerIt!=dropsBeforeLower.end()){
const ItemDrop&drop=ItemDrop::drops[*dropsBeforeLowerIt];
const ItemDrop&drop{*dropsBeforeLowerIt};
drop.Draw();
++dropsBeforeLowerIt;
}
@ -1540,7 +1477,7 @@ void AiL::RenderWorld(float fElapsedTime){
break;
}
while(dropsAfterLowerIt!=dropsAfterLower.end()){
const ItemDrop&drop=ItemDrop::drops[*dropsAfterLowerIt];
const ItemDrop&drop{*dropsAfterLowerIt};
if(drop.pos.y<tile->group->GetCollisionRange().middle().y){
drop.Draw();
++dropsAfterLowerIt;
@ -1570,16 +1507,16 @@ void AiL::RenderWorld(float fElapsedTime){
#pragma endregion
#pragma region Remaining Rendering
while(monstersBeforeLowerIt!=monstersBeforeLower.end()){
Monster*const m=*monstersBeforeLowerIt;
m->Draw();
const Monster&m=**monstersBeforeLowerIt;
m.Draw();
++monstersBeforeLowerIt;
}
for(const Effect*const e:backgroundEffectsLower){
for(std::unique_ptr<Effect>&e:backgroundEffectsLower){
e->_Draw();
}
while(dropsBeforeLowerIt!=dropsBeforeLower.end()){
const int dropInd=*dropsBeforeLowerIt;
ItemDrop::drops[dropInd].Draw();
const ItemDrop&drop{*dropsBeforeLowerIt};
drop.Draw();
++dropsBeforeLowerIt;
}
if(!player->rendered&&!player->upperLevel){
@ -1588,22 +1525,24 @@ void AiL::RenderWorld(float fElapsedTime){
vf2d shadowScale=vf2d{8*player->GetSizeMult()/3.f,1}/std::max(1.f,player->GetZ()/24);
view.DrawDecal(player->GetPos()-vf2d{3,3}*shadowScale/2+vf2d{0,6*player->GetSizeMult()},GFX["circle.png"].Decal(),shadowScale,BLACK);
}
if(player->IsUsingAdditiveBlending())SetDecalMode(DecalMode::ADDITIVE);
else SetDecalMode(DecalMode::NORMAL);
RenderPlayer(player->GetPos(),{1,1});
}
while(monstersAfterLowerIt!=monstersAfterLower.end()){
Monster*const m=*monstersAfterLowerIt;
m->Draw();
const Monster&m=**monstersAfterLowerIt;
m.Draw();
++monstersAfterLowerIt;
}
while(dropsAfterLowerIt!=dropsAfterLower.end()){
const int dropInd=*dropsAfterLowerIt;
ItemDrop::drops[dropInd].Draw();
const ItemDrop&drop{*dropsAfterLowerIt};
drop.Draw();
++dropsAfterLowerIt;
}
for(const IBullet*const b:bulletsLower){
for(std::unique_ptr<IBullet>&b:bulletsLower){
b->_Draw();
}
for(const Effect*const e:foregroundEffectsLower){
for(std::unique_ptr<Effect>&e:foregroundEffectsLower){
e->_Draw();
}
#pragma endregion
@ -1751,7 +1690,7 @@ void AiL::RenderWorld(float fElapsedTime){
break;
}
while(dropsBeforeUpperIt!=dropsBeforeUpper.end()){
const ItemDrop&drop=ItemDrop::drops[*dropsBeforeUpperIt];
const ItemDrop&drop{*dropsBeforeUpperIt};
if(drop.pos.y<topTileY){
drop.Draw();
++dropsBeforeUpperIt;
@ -1767,7 +1706,7 @@ void AiL::RenderWorld(float fElapsedTime){
++monstersBeforeUpperIt;
}
while(dropsBeforeUpperIt!=dropsBeforeUpper.end()){
const ItemDrop&drop=ItemDrop::drops[*dropsBeforeUpperIt];
const ItemDrop&drop{*dropsBeforeUpperIt};
drop.Draw();
++dropsBeforeUpperIt;
}
@ -1776,6 +1715,8 @@ void AiL::RenderWorld(float fElapsedTime){
vf2d shadowScale=vf2d{8*player->GetSizeMult()/3.f,1}/std::max(1.f,player->GetZ()/24);
view.DrawDecal(player->GetPos()-vf2d{3,3}*shadowScale/2+vf2d{0,6*player->GetSizeMult()},GFX["circle.png"].Decal(),shadowScale,BLACK);
}
if(player->IsUsingAdditiveBlending())SetDecalMode(DecalMode::ADDITIVE);
else SetDecalMode(DecalMode::NORMAL);
RenderPlayer(player->GetPos(),{1,1});
}
while(monstersAfterUpperIt!=monstersAfterUpper.end()){
@ -1788,7 +1729,7 @@ void AiL::RenderWorld(float fElapsedTime){
break;
}
while(dropsAfterUpperIt!=dropsAfterUpper.end()){
const ItemDrop&drop=ItemDrop::drops[*dropsAfterUpperIt];
const ItemDrop&drop{*dropsAfterUpperIt};
if(drop.pos.y<topTileY){
drop.Draw();
++dropsAfterUpperIt;
@ -1812,7 +1753,7 @@ void AiL::RenderWorld(float fElapsedTime){
break;
}
while(dropsBeforeUpperIt!=dropsBeforeUpper.end()){
const ItemDrop&drop=ItemDrop::drops[*dropsBeforeUpperIt];
const ItemDrop&drop{*dropsBeforeUpperIt};
if(drop.pos.y<tile->group->GetCollisionRange().middle().y){
drop.Draw();
++dropsBeforeUpperIt;
@ -1828,7 +1769,7 @@ void AiL::RenderWorld(float fElapsedTime){
++monstersBeforeUpperIt;
}
while(dropsBeforeUpperIt!=dropsBeforeUpper.end()){
const ItemDrop&drop=ItemDrop::drops[*dropsBeforeUpperIt];
const ItemDrop&drop{*dropsBeforeUpperIt};
drop.Draw();
++dropsBeforeUpperIt;
}
@ -1837,6 +1778,8 @@ void AiL::RenderWorld(float fElapsedTime){
vf2d shadowScale=vf2d{8*player->GetSizeMult()/3.f,1}/std::max(1.f,player->GetZ()/24);
view.DrawDecal(player->GetPos()-vf2d{3,3}*shadowScale/2+vf2d{0,6*player->GetSizeMult()},GFX["circle.png"].Decal(),shadowScale,BLACK);
}
if(player->IsUsingAdditiveBlending())SetDecalMode(DecalMode::ADDITIVE);
else SetDecalMode(DecalMode::NORMAL);
RenderPlayer(player->GetPos(),{1,1});
}
while(monstersAfterUpperIt!=monstersAfterUpper.end()){
@ -1849,7 +1792,7 @@ void AiL::RenderWorld(float fElapsedTime){
break;
}
while(dropsAfterUpperIt!=dropsAfterUpper.end()){
const ItemDrop&drop=ItemDrop::drops[*dropsAfterUpperIt];
const ItemDrop&drop{*dropsAfterUpperIt};
if(drop.pos.y<tile->group->GetCollisionRange().middle().y){
drop.Draw();
++dropsAfterUpperIt;
@ -1871,16 +1814,16 @@ void AiL::RenderWorld(float fElapsedTime){
#pragma endregion
#pragma region Remaining Upper Rendering
while(monstersBeforeUpperIt!=monstersBeforeUpper.end()){
Monster*const m=*monstersBeforeUpperIt;
m->Draw();
const Monster&m=**monstersBeforeUpperIt;
m.Draw();
++monstersBeforeUpperIt;
}
for(const Effect*const e:backgroundEffectsUpper){
for(std::unique_ptr<Effect>&e:backgroundEffectsUpper){
e->_Draw();
}
while(dropsBeforeUpperIt!=dropsBeforeUpper.end()){
const int dropInd=*dropsBeforeUpperIt;
ItemDrop::drops[dropInd].Draw();
const ItemDrop&drop{*dropsBeforeUpperIt};
drop.Draw();
++dropsBeforeUpperIt;
}
if(!player->rendered&&player->upperLevel){
@ -1892,19 +1835,19 @@ void AiL::RenderWorld(float fElapsedTime){
RenderPlayer(player->GetPos(),{1,1});
}
while(monstersAfterUpperIt!=monstersAfterUpper.end()){
Monster*const m=*monstersAfterUpperIt;
m->Draw();
const Monster&m=**monstersAfterUpperIt;
m.Draw();
++monstersAfterUpperIt;
}
while(dropsAfterUpperIt!=dropsAfterUpper.end()){
const int dropInd=*dropsAfterUpperIt;
ItemDrop::drops[dropInd].Draw();
const ItemDrop&drop{*dropsAfterUpperIt};
drop.Draw();
++dropsAfterUpperIt;
}
for(const IBullet*const b:bulletsUpper){
for(std::unique_ptr<IBullet>&b:bulletsUpper){
b->_Draw();
}
for(const Effect*const e:foregroundEffectsUpper){
for(std::unique_ptr<Effect>&e:foregroundEffectsUpper){
e->_Draw();
}
#pragma endregion

@ -173,8 +173,6 @@ public:
private:
std::vector<std::unique_ptr<Effect>>foregroundEffects,backgroundEffects,foregroundEffectsToBeInserted,backgroundEffectsToBeInserted;
std::vector<TileRenderData*>tilesWithCollision,tilesWithoutCollision;
std::vector<int>dropsBeforeLower,dropsAfterLower,dropsBeforeUpper,dropsAfterUpper;
std::vector<ZoneData>endZones,upperEndZones;
std::vector<vf2d>circleCooldownPoints;
std::vector<vf2d>squareCircleCooldownPoints;
std::map<std::string,TilesetData>MAP_TILESETS;
@ -190,9 +188,6 @@ private:
int bridgeLayerIndex=-1;
float bridgeFadeFactor=0.f;
int DEBUG_PATHFINDING=0;
std::vector<Monster*>monstersBeforeLower,monstersAfterLower,monstersBeforeUpper,monstersAfterUpper;
std::vector<IBullet*>bulletsLower,bulletsUpper;
std::vector<Effect*>backgroundEffectsLower,backgroundEffectsUpper,foregroundEffectsLower,foregroundEffectsUpper;
float reflectionUpdateTimer=0;
float reflectionStepTime=0;
std::set<vi2d>visibleTiles;

@ -62,11 +62,16 @@ void Monster::STRATEGY::GHOST_OF_PIRATE_CAPTAIN(Monster&m,float fElapsedTime,std
};
static const uint8_t PHASE_COUNT{uint8_t(DATA.GetProperty("MonsterStrategy.Ghost of Pirate Captain.Cannon Cycle").GetValueCount())};
static uint8_t TOTAL_CANNON_SHOTS{0};
const auto AdvanceCannonPhase{[&m,&strategy](){
m.GetFloat(A::CANNON_TIMER)=0.f;
//if(m.GetInt(A::CANNON_PHASE)+1>=PHASE_COUNT)m.GetInt(A::CANNON_SHOT_TYPE)=util::random()%5;
m.GetInt(A::CANNON_PHASE)=(m.GetInt(A::CANNON_PHASE)+1)%PHASE_COUNT;
const int prevCannonPhase{m.I(A::CANNON_PHASE)};
m.I(A::CANNON_PHASE)=(m.I(A::CANNON_PHASE)+1)%PHASE_COUNT;
if(prevCannonPhase>m.I(A::CANNON_PHASE)){//Phase has wrapped around, reset cannon shot count.
m.I(A::CANNON_SHOT_COUNT)=0;
}
}};
if(m.F(A::SHRAPNEL_SHOT_FALL_TIMER)>0.f){
@ -82,22 +87,24 @@ void Monster::STRATEGY::GHOST_OF_PIRATE_CAPTAIN(Monster&m,float fElapsedTime,std
}
switch(PHASE()){
enum CannonPhaseType{
CANNON_SHOT,
SILENCE,
SHRAPNEL_SHOT,
};
case INIT:{
for(int i:std::ranges::iota_view(0U,PHASE_COUNT)){
m.VEC(A::CANNON_PHASES).emplace_back(DATA.GetProperty("MonsterStrategy.Ghost of Pirate Captain.Cannon Cycle").GetInt(i));
const int cannonCycle{DATA.GetProperty("MonsterStrategy.Ghost of Pirate Captain.Cannon Cycle").GetInt(i)};
m.VEC(A::CANNON_PHASES).emplace_back(cannonCycle);
if(cannonCycle==CANNON_SHOT)TOTAL_CANNON_SHOTS++;
}
m.I(A::CANNON_SHOT_TYPE)=BOMBARDMENT;
m.I(A::CANNON_SHOT_TYPE)=PREDICTION;
SETPHASE(NORMAL);
}break;
case NORMAL:{
m.F(A::CANNON_TIMER)+=fElapsedTime;
const int phase{std::any_cast<int>(m.VEC(A::CANNON_PHASES)[m.I(A::CANNON_PHASE)])};
switch(phase){
enum CannonPhaseType{
CANNON_SHOT,
SILENCE,
SHRAPNEL_SHOT,
};
case CANNON_SHOT:{//Normal Cannon Shot. Takes on one of five varieties.
if(m.F(A::CANNON_TIMER)>=ConfigFloat("Cannon Shot Delay")){
switch(m.I(A::CANNON_SHOT_TYPE)){
@ -108,19 +115,30 @@ void Monster::STRATEGY::GHOST_OF_PIRATE_CAPTAIN(Monster&m,float fElapsedTime,std
CreateBullet(FallingBullet)("cannonball.png",targetPos,ConfigVec("Cannon Vel"),ConfigFloatArr("Cannon Vel",2),ConfigFloat("Indicator Time"),ConfigPixels("Cannon Radius"),ConfigInt("Cannon Damage"),m.OnUpperLevel(),false,ConfigFloat("Cannon Knockback Amt"),ConfigFloat("Cannon Shot Impact Time"),false,ConfigPixel("Cannon Spell Circle Color"),vf2d{ConfigFloat("Cannon Radius")/100.f*1.75f,ConfigFloat("Cannon Radius")/100.f*1.75f},util::random(2*PI),util::random(2*PI),util::degToRad(ConfigFloat("Cannon Spell Circle Rotation Spd")),ConfigPixel("Cannon Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Cannon Spell Insignia Rotation Spd")))EndBullet;
}break;
case PRECISE_BOMBARDMENT:{
const float randomAng{util::random_range(0,2*PI)};
const float range{util::random_range(0,ConfigPixels("Precise Bombardment Max Distance"))};
const vf2d targetPos{game->GetPlayer()->GetPos()+vf2d{range,randomAng}.cart()};
CreateBullet(FallingBullet)("cannonball.png",targetPos,ConfigVec("Cannon Vel"),ConfigFloatArr("Cannon Vel",2),ConfigFloat("Indicator Time"),ConfigPixels("Cannon Radius"),ConfigInt("Cannon Damage"),m.OnUpperLevel(),false,ConfigFloat("Cannon Knockback Amt"),ConfigFloat("Cannon Shot Impact Time"),false,ConfigPixel("Cannon Spell Circle Color"),vf2d{ConfigFloat("Cannon Radius")/100.f*1.75f,ConfigFloat("Cannon Radius")/100.f*1.75f},util::random(2*PI),util::random(2*PI),util::degToRad(ConfigFloat("Cannon Spell Circle Rotation Spd")),ConfigPixel("Cannon Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Cannon Spell Insignia Rotation Spd")))EndBullet;
}break;
case LINE:{
//Draw a line from one side of the screen to the other, drawing through the middle.
if(m.I(A::CANNON_SHOT_COUNT)==0)m.F(A::LINE_SHOT_ANG)=util::random_range(0,2*PI);
const vf2d targetPos{geom2d::line{game->GetPlayer()->GetPos()+vf2d{float(game->ScreenHeight()),m.F(A::LINE_SHOT_ANG)}.cart(),game->GetPlayer()->GetPos()+vf2d{float(game->ScreenHeight()),m.F(A::LINE_SHOT_ANG)+PI}.cart()}.upoint(float(m.I(A::CANNON_SHOT_COUNT))/TOTAL_CANNON_SHOTS)};
CreateBullet(FallingBullet)("cannonball.png",targetPos,ConfigVec("Cannon Vel"),ConfigFloatArr("Cannon Vel",2),ConfigFloat("Indicator Time"),ConfigPixels("Cannon Radius"),ConfigInt("Cannon Damage"),m.OnUpperLevel(),false,ConfigFloat("Cannon Knockback Amt"),ConfigFloat("Cannon Shot Impact Time"),false,ConfigPixel("Cannon Spell Circle Color"),vf2d{ConfigFloat("Cannon Radius")/100.f*1.75f,ConfigFloat("Cannon Radius")/100.f*1.75f},util::random(2*PI),util::random(2*PI),util::degToRad(ConfigFloat("Cannon Spell Circle Rotation Spd")),ConfigPixel("Cannon Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Cannon Spell Insignia Rotation Spd")))EndBullet;
}break;
case SHARPSHOOTER:{
if(m.I(A::CANNON_SHOT_COUNT)%2==0)CreateBullet(FallingBullet)("cannonball.png",game->GetPlayer()->GetPos(),ConfigVec("Cannon Vel"),ConfigFloatArr("Cannon Vel",2),ConfigFloat("Indicator Time"),ConfigPixels("Cannon Radius"),ConfigInt("Cannon Damage"),m.OnUpperLevel(),false,ConfigFloat("Cannon Knockback Amt"),ConfigFloat("Cannon Shot Impact Time"),false,ConfigPixel("Cannon Spell Circle Color"),vf2d{ConfigFloat("Cannon Radius")/100.f*1.75f,ConfigFloat("Cannon Radius")/100.f*1.75f},util::random(2*PI),util::random(2*PI),util::degToRad(ConfigFloat("Cannon Spell Circle Rotation Spd")),ConfigPixel("Cannon Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Cannon Spell Insignia Rotation Spd")))EndBullet;
}break;
case PREDICTION:{
LOG(std::format("Previous Pos: {} Current: {}",game->GetPlayer()->GetPreviousPos().str(),game->GetPlayer()->GetPos().str()));
const float angle{util::angleTo(game->GetPlayer()->GetPreviousPos(),game->GetPlayer()->GetPos())};
const float range{util::random_range(0,100.f*game->GetPlayer()->GetMoveSpdMult())*ConfigFloat("Cannon Shot Impact Time")};
const vf2d targetPos{game->GetPlayer()->GetPos()+vf2d{range,angle}.cart()};
CreateBullet(FallingBullet)("cannonball.png",targetPos,ConfigVec("Cannon Vel"),ConfigFloatArr("Cannon Vel",2),ConfigFloat("Indicator Time"),ConfigPixels("Cannon Radius"),ConfigInt("Cannon Damage"),m.OnUpperLevel(),false,ConfigFloat("Cannon Knockback Amt"),ConfigFloat("Cannon Shot Impact Time"),false,ConfigPixel("Cannon Spell Circle Color"),vf2d{ConfigFloat("Cannon Radius")/100.f*1.75f,ConfigFloat("Cannon Radius")/100.f*1.75f},util::random(2*PI),util::random(2*PI),util::degToRad(ConfigFloat("Cannon Spell Circle Rotation Spd")),ConfigPixel("Cannon Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Cannon Spell Insignia Rotation Spd")))EndBullet;
}break;
}
AdvanceCannonPhase();
m.I(A::CANNON_SHOT_COUNT)++;
}
}break;
case SILENCE:{

@ -69,7 +69,7 @@ vf2d ItemDrop::GetPos()const{
return pos;
}
bool ItemDrop::OnUpperLevel(){
bool ItemDrop::OnUpperLevel()const{
return upperLevel;
}

@ -59,7 +59,7 @@ class ItemDrop{
public:
static void Initialize();
vf2d GetPos()const;
bool OnUpperLevel();
bool OnUpperLevel()const;
void Draw()const;
static void UpdateDrops(float fElapsedTime);
static const std::vector<ItemDrop>&GetDrops();

@ -169,5 +169,7 @@ enum class Attribute{
CANNON_PHASES,
SHRAPNEL_SHOT_COUNT,
SHRAPNEL_SHOT_FALL_TIMER,
CANNON_SHOT_COUNT,
LINE_SHOT_ANG,
LAST_PLAYER_POS,
};

@ -399,6 +399,7 @@ void Player::Update(float fElapsedTime){
hpRecoveryTimer=std::max(0.f,hpRecoveryTimer-fElapsedTime);
hp6RecoveryTimer=std::max(0.f,hp6RecoveryTimer-fElapsedTime);
hp4RecoveryTimer=std::max(0.f,hp4RecoveryTimer-fElapsedTime);
const vf2d previousPosTemp{GetPos()}; //The logic here is that the previous position must be a different value from the actual position and should only change when the position of the player actually changes, this means we must wait for the entire frame to resolve to see if any movement has occurred to update to the "new previous position". This variable is resolved at the bottom of this Update function.
RunTimers();
PerformHPRecovery();
@ -855,6 +856,10 @@ void Player::Update(float fElapsedTime){
}
}
#pragma endregion
if(previousPosTemp!=GetPos()){
previousPos=previousPosTemp; //The logic here is that the previous position must be a different value from the actual position and should only change when the position of the player actually changes, this means we must wait for the entire frame to resolve to see if any movement has occurred to update to the "new previous position". The previous position temp variable is set at the top of this Update function.
}
}
float Player::GetSwordSwingTimer(){
@ -2323,4 +2328,7 @@ const bool Player::HasBuff(BuffType buff)const{
}
const bool Player::CoveredInInk()const{
return HasBuff(BuffType::INK_SLOWDOWN);
}
const vf2d&Player::GetPreviousPos()const{
return previousPos;
}

@ -339,6 +339,7 @@ public:
void PrepareCast(Ability&ability); //NOTE: This usually is not called unless we are running tests! PrepareCast is meant to be used before we use CastSpell in unit tests.
void SetTestScreenAimingLocation(vf2d forcedAimingLoc);
const bool CoveredInInk()const;
const vf2d&GetPreviousPos()const; //The position the player was at on the last frame, can be used for comparison purposes to predict where the player may be next.
private:
static std::vector<std::reference_wrapper<Ability>>ABILITY_LIST;
const int SHIELD_CAPACITY{32};
@ -433,6 +434,7 @@ private:
bool catForm{false};
std::optional<vf2d>testAimingLoc{};
vf2d addedVel{};
vf2d previousPos{pos};
protected:
const float ATTACK_COOLDOWN="Warrior.Auto Attack.Cooldown"_F;
const float MAGIC_ATTACK_COOLDOWN="Wizard.Auto Attack.Cooldown"_F;

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 1
#define VERSION_MINOR 3
#define VERSION_PATCH 0
#define VERSION_BUILD 11980
#define VERSION_BUILD 11997
#define stringify(a) stringify_(a)
#define stringify_(a) #a

Loading…
Cancel
Save