You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
VirusAttack/olcCodeJam2023Entry/Scenario.cpp

819 lines
25 KiB

#include "Scenario.h"
#include "TileManager.h"
#include "olcUTIL_Geometry2D.h"
Scenario::Scenario(std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_ptr<Renderable>>&IMAGES,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::string&objective,TileTransformedView&game,GameFlags&flags)
:units(units),IMAGES(IMAGES),SOUNDS(SOUNDS),objective(objective),game(game),flags(flags){}
Scenario::~Scenario(){};
void Scenario::_Start(){
state=0;
camera=utils::Camera2D{game.GetPGE()->GetScreenSize(),game.GetWorldOffset()};
camera.SetLazyFollowRate(2);
camera.SetMode(utils::Camera2D::Mode::LazyFollow);
targetPos={96,96};
box.SetVisible(false);
initialWaitTime=3;
camera.SetTarget(targetPos);
missionCompletedTimer=0;
transitionToNextLevel=false;
setupEasyMode=false;
Start();
}
void Scenario::Start(){};
void Scenario::_Update(Resources&enemy_resources,std::vector<std::shared_ptr<CollectionPoint>>&collectionPoints,int availableMemory,std::vector<std::shared_ptr<Unit>>&queuedUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS){
initialWaitTime=std::max(0.f,initialWaitTime-game.GetPGE()->GetElapsedTime());
missionFinishWaitTime=std::max(0.f,missionFinishWaitTime-game.GetPGE()->GetElapsedTime());
smallTimePass=std::min(1.f,smallTimePass+game.GetPGE()->GetElapsedTime());
if(flags.playerInControl){
smallTimePass=0;
}
if(missionCompleted){
missionCompletedTimer+=game.GetPGE()->GetElapsedTime();
} else {
missionCompleted=MissionCompleted();
}
if(flags.playerInControl){
RunAI(enemy_resources,collectionPoints,availableMemory,queuedUnits,SOUNDS);
}
if(initialWaitTime==0){
Update();
}
};
void Scenario::RunAI(Resources&enemy_resources,std::vector<std::shared_ptr<CollectionPoint>>&collectionPoints,int availableMemory,std::vector<std::shared_ptr<Unit>>&queuedUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS){
if(!setupEasyMode&&flags.difficulty==0){
enemy_resources={100,100,100,100,100};
}
attackTimer=std::max(0.f,attackTimer-game.GetPGE()->GetElapsedTime());
unitBuildTimer=std::max(0.f,unitBuildTimer-game.GetPGE()->GetElapsedTime());
std::weak_ptr<Unit>baseOfOperations;
std::weak_ptr<Unit>enemyBaseOfOperations;
for(auto&u:units){
if(!u->IsFriendly()&&u->IsRAMBank()){
baseOfOperations=u;
break;
}
}
for(auto&u:units){
if(u->IsFriendly()&&u->IsRAMBank()){
enemyBaseOfOperations=u;
break;
}
}
if(baseOfOperations.expired()){
for(auto&u:units){
if(!u->IsFriendly()){
baseOfOperations=u;
break;
}
}
}
//See if there are collectors, if so send memory allocator units towards them.
if(!baseOfOperations.expired()){
std::sort(collectionPoints.begin(),collectionPoints.end(),[&](std::shared_ptr<CollectionPoint>cp1,std::shared_ptr<CollectionPoint>cp2){
geom2d::line<float>toCP1={cp1->pos,baseOfOperations.lock()->GetPos()};
geom2d::line<float>toCP2={cp2->pos,baseOfOperations.lock()->GetPos()};
return toCP1.length()<toCP2.length();});
}
for(auto&cp:collectionPoints){
if(cp->attachedUnit.expired()){
if(cpCheckTimer.count(cp.get())==0||cpCheckTimer[cp.get()]<=0){
for(auto&u:units){
if(!u->IsFriendly()&&u->IsAllocator()&&u->attachTarget.expired()){
//Tell this unit to move towards that collection point.
u->SetTargetCollectionPoint(cp,u);
break;
}
}
//Hasn't been checked recently.
cpCheckTimer[cp.get()]=60;
}
}
}
for(auto&key:cpCheckTimer){
cpCheckTimer[key.first]=std::max(0.0f,game.GetPGE()->GetElapsedTime());
}
int memoryAllocatorCount=0;
for(auto&u:units){
if(!u->IsFriendly()&&u->IsAllocator()){
memoryAllocatorCount++;
}
}
if(memoryAllocatorCount<3){
for(auto&u:units){
if(!u->IsFriendly()&&u->IsRAMBank()){
AttemptBuild(UnitType::MemoryAllocator,u->GetPos(),MemoryAllocator::resourceCost,enemy_resources,availableMemory,queuedUnits);
}
}
}
//Randomly turn memory allocators into other units.
if(unitBuildTimer==0){
for(auto&u:units){
if(!u->IsFriendly()&&u->IsAllocator()){
std::array<UnitType,10>unitChoiceList={UnitType::LeftShifter,UnitType::LeftShifter,UnitType::RightShifter,UnitType::RightShifter,
UnitType::Corrupter,UnitType::MemorySwapper,UnitType::BitRestorer,UnitType::BitRestorer,UnitType::_Platform,UnitType::Corrupter};
std::array<std::vector<Memory>,10>unitResourceCostList={LeftShifter::resourceCost,LeftShifter::resourceCost,RightShifter::resourceCost,RightShifter::resourceCost,
Corrupter::resourceCost,MemorySwapper::resourceCost,BitRestorer::resourceCost,BitRestorer::resourceCost,_Platform::resourceCost,Corrupter::resourceCost};
int randomIndex=rand()%unitChoiceList.size();
UnitType buildUnit=unitChoiceList[randomIndex];
int totalCost=0;
for(int i=0;i<unitResourceCostList[randomIndex].size();i++){
totalCost+=unitResourceCostList[randomIndex][i].size;
}
if(totalCost<=availableMemory){
#define Build(type) \
case UnitType::type:{ \
u->SetBuildUnit(8,std::make_shared<type>(game.GetPGE(),u->GetPos(),IMAGES,false),SOUNDS); \
}break;
switch(buildUnit){
Build(LeftShifter)
Build(RightShifter)
Build(BitRestorer)
Build(_Platform)
Build(Corrupter)
Build(MemorySwapper)
}
if(enemy_resources.health>0){enemy_resources.health=std::max(0,enemy_resources.health-totalCost);}else
if(enemy_resources.atkSpd>0){enemy_resources.atkSpd=std::max(0,enemy_resources.atkSpd-totalCost);}else
if(enemy_resources.moveSpd>0){enemy_resources.moveSpd=std::max(0,enemy_resources.moveSpd-totalCost);}else
if(enemy_resources.range>0){enemy_resources.range=std::max(0,enemy_resources.range-totalCost);}else
{enemy_resources.procedure=std::max(0,enemy_resources.procedure-totalCost);
}
}
}
if(!u->IsFriendly()&&u->IsPlatform()){
std::array<UnitType,7>unitChoiceList={UnitType::RAMBank,UnitType::Refresher,UnitType::Refresher,UnitType::Turret,
UnitType::Turret,UnitType::Turret,UnitType::MemoryGuard};
std::array<std::vector<Memory>,7>unitResourceCostList={RAMBank::resourceCost,Refresher::resourceCost,Refresher::resourceCost,Turret::resourceCost,
Turret::resourceCost,Turret::resourceCost,MemoryGuard::resourceCost};
int randomIndex=rand()%unitChoiceList.size();
UnitType buildUnit=unitChoiceList[randomIndex];
int totalCost=0;
for(int i=0;i<unitResourceCostList[randomIndex].size();i++){
totalCost+=unitResourceCostList[randomIndex][i].size;
}
if(totalCost<=availableMemory){
#define Build(type) \
case UnitType::type:{ \
u->SetBuildUnit(8,std::make_shared<type>(game.GetPGE(),u->GetPos(),IMAGES,false),SOUNDS); \
}break;
switch(buildUnit){
Build(RAMBank)
Build(Refresher)
Build(Turret)
Build(MemoryGuard)
}
if(enemy_resources.health>0){enemy_resources.health=std::max(0,enemy_resources.health-totalCost);}else
if(enemy_resources.atkSpd>0){enemy_resources.atkSpd=std::max(0,enemy_resources.atkSpd-totalCost);}else
if(enemy_resources.moveSpd>0){enemy_resources.moveSpd=std::max(0,enemy_resources.moveSpd-totalCost);}else
if(enemy_resources.range>0){enemy_resources.range=std::max(0,enemy_resources.range-totalCost);}else
{enemy_resources.procedure=std::max(0,enemy_resources.procedure-totalCost);
}
}
}
switch(flags.difficulty){
case 0:{
unitBuildTimer=120;
}break;
case 1:{
unitBuildTimer=60;
}break;
case 2:{
unitBuildTimer=10;
}break;
}
}
}
if(attackTimer==0){
if(!enemyBaseOfOperations.expired()){
for(auto&u:units){
if(!u->IsFriendly()&&rand()%3==0){
if(u->CanInteractWithEnemies()&&!u->IsAllocator()&&u->CanMove()){
u->SetTargetUnit(enemyBaseOfOperations);
}
}
}
for(auto&u:units){
if(!u->IsFriendly()&&u->GetCurrentTarget().expired()&&u->CanInteractWithAllies()){
if(rand()%5==0){
u->SetTargetLocation(enemyBaseOfOperations.lock()->GetPos());
}
}
}
}
switch(flags.difficulty){
case 0:{
attackTimer=999;
}break;
case 1:{
attackTimer=300;
}break;
case 2:{
attackTimer=120;
}break;
}
}
}
/*
std::shared_ptr<UnitClass>buildUnit=std::make_shared<UnitClass>(this,u->GetPos(),IMAGES,u->IsFriendly()); \
u->SetBuildUnit(CONSTANT::UNIT_BUILD_TIME,std::move(buildUnit),SOUNDS); \
*/
bool Scenario::AttemptBuild(UnitType unit,vf2d pos,std::vector<Memory>&resourceCost,Resources&enemy_resources,int availableMemory,std::vector<std::shared_ptr<Unit>>&queuedUnits){
int enemyTotalResources=enemy_resources.atkSpd+enemy_resources.health+enemy_resources.moveSpd+enemy_resources.procedure+enemy_resources.range;
int totalCost=0;
for(int i=0;i<resourceCost.size();i++){
totalCost+=resourceCost[i].size;
}
if(totalCost>availableMemory)return false;
if(enemyTotalResources>=totalCost){
if(enemy_resources.health>0){enemy_resources.health=std::max(0,enemy_resources.health-totalCost);}else
if(enemy_resources.atkSpd>0){enemy_resources.atkSpd=std::max(0,enemy_resources.atkSpd-totalCost);}else
if(enemy_resources.moveSpd>0){enemy_resources.moveSpd=std::max(0,enemy_resources.moveSpd-totalCost);}else
if(enemy_resources.range>0){enemy_resources.range=std::max(0,enemy_resources.range-totalCost);}else
{enemy_resources.procedure=std::max(0,enemy_resources.procedure-totalCost);}
#define TranslateUnit(type) \
case UnitType::type:{ \
queuedUnits.emplace_back(std::make_shared<type>(game.GetPGE(),pos,IMAGES,false)); \
}break;
switch(unit){
TranslateUnit(MemoryAllocator)
TranslateUnit(LeftShifter)
TranslateUnit(RightShifter)
TranslateUnit(BitRestorer)
TranslateUnit(MemorySwapper)
TranslateUnit(Corrupter)
TranslateUnit(RAMBank)
TranslateUnit(MemoryGuard)
TranslateUnit(Refresher)
TranslateUnit(Turret)
TranslateUnit(_Platform)
}
}
return true;
}
bool Scenario::MissionCompleted(){return false;}
void Scenario::Update(){};
void Scenario::Draw(){
if(objective.length()>0){
game.GetPGE()->DrawShadowStringDecal({4,24},"Objective:");
game.GetPGE()->DrawShadowStringDecal({6,36},objective);
game.GetPGE()->DrawShadowStringDecal({4,24},missionCompleted?"Objective Complete!":"Objective:",missionCompleted?GREEN:WHITE);
vf2d textSize=game.GetPGE()->GetTextSize(objective);
game.GetPGE()->DrawShadowStringDecal({6,36},objective,missionCompleted?GREEN:WHITE);
if(missionCompleted&&missionFinishWaitTime==0){
game.GetPGE()->FillRectDecal(vf2d{6,36}+vf2d{0,textSize.y/2-1},{textSize.x,3});
std::string continueText="< Press [Spacebar] to continue >";
vf2d textScale={2,3};
vf2d textSize=game.GetPGE()->GetTextSizeProp(continueText)*textScale;
game.GetPGE()->DrawShadowStringPropDecal(game.GetPGE()->GetScreenSize()/2-textSize/2+vf2d{0,72},continueText,{255,255,255,uint8_t(abs(sin(2*missionCompletedTimer))*255)},{0,0,0,uint8_t(abs(sin(2*missionCompletedTimer))*255)},textScale);
if(game.GetPGE()->GetKey(SPACE).bPressed){
transitionToNextLevel=true;
}
}
}
Resources temp={0,0,0,0,0};
box.UpdateAndDraw({24,64},game.GetPGE(),temp,IMAGES,0,0);
}
void Scenario::SetCameraTarget(vf2d pos,bool instant){
if(instant){camera.SetMode(utils::Camera2D::Mode::Simple);} else {camera.SetMode(utils::Camera2D::Mode::LazyFollow);}
targetPos=pos;
camera.SetTarget(targetPos);
camera.Update(game.GetPGE()->GetElapsedTime());
game.SetWorldOffset(camera.GetViewPosition());
}
void Scenario::SetObjective(std::string objective){
this->objective=objective;
}
void Scenario::RevealTiles(vf2d pos){
for(int y=-1;y<=1;y++){
for(int x=-1;x<=1;x++){
vi2d basePos={int(pos.x+x*96),int(pos.y+y*96)};
TileManager::visibleTiles[{basePos.x/96,basePos.y/96}]=30;
}
}
}
Stage1::Stage1(std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_ptr<Renderable>>&IMAGES,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::string&objective,TileTransformedView&game,GameFlags&flags)
:Scenario(units,IMAGES,SOUNDS,objective,game,flags){}
void Stage1::Start(){
flags.unitMetersGreyedOut=true;
flags.playerInControl=false;
nextLevel=LevelName::STAGE2;
};
void Scenario::DisplayBox(std::string text,bool scaryHoodedFigure){
if(smallTimePass==1){
box.Initialize(text,{24,64},"",scaryHoodedFigure?IMAGES[SPOOK_HOODED_FIGURE].get():IMAGES[HOODED_FIGURE].get(),{378,28},SOUNDS[Sound::VOICEOVER].get());
}
}
void Stage1::Update(){
switch(state){
case 0:{
DisplayBox("Hello Hacker, thank you for taking on this request for me.");
if(box.bPressed){
state=1;
}
}break;
case 1:{
DisplayBox("It appears we have no time to waste, many sectors are already infected and the virus spread will just keep getting worse.");
if(box.bPressed){
state=2;
SOUNDS[Sound::PING]->PlayCentered();
RevealTiles({320,320});
}
}break;
case 2:{
SetCameraTarget({320,320});
if(camera.ReachedTarget()){
state=3;
}
}break;
case 3:{
DisplayBox("Your mission is to take out all the RAM banks from the system, this will stop any further creation and spread of viruses.");
if(box.bPressed){
state=4;
}
}break;
case 4:{
SetCameraTarget({128,128});
if(camera.ReachedTarget()){
state=5;
}
}break;
case 5:{
DisplayBox("The yellow bars represent units' allocated Health memory. Take out the enemies' and make sure you always have at least 1 bit of it.");
if(box.bPressed){
state=6;
}
}break;
case 6:{
DisplayBox("Drag over your target unit and then select a target location via right-click.");
if(box.bPressed){
state=7;
}
}break;
case 7:{
SetObjective("Defeat the RAM bank");
DisplayBox("That should be all you need for now. I'll be back after my coffee break.");
if(box.bPressed){
state=8;
box.SetVisible(false);
flags.playerInControl=true;
}
}break;
case 8:{
}break;
}
};
bool Stage1::MissionCompleted(){
for(auto&u:units){
if(!u->IsFriendly()&&u->IsRAMBank()){
return false;
}
}
return true;
}
Stage2::Stage2(std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_ptr<Renderable>>&IMAGES,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::string&objective,TileTransformedView&game,GameFlags&flags)
:Scenario(units,IMAGES,SOUNDS,objective,game,flags){}
void Stage2::Start(){
flags.playerInControl=false;
flags.limitedBuildOptions=true;
flags.flashMemoryBar=false;
SetCameraTarget({7*24,10*24},true);
nextLevel=LevelName::STAGE3;
};
void Stage2::Update(){
switch(state){
case 0:{
DisplayBox("You took care of that sector flawlessly Hacker, this next one needs a bit more hand-holding.");
if(box.bPressed){
state=1;
}
}break;
case 1:{
SetObjective("Create a RAM bank.");
DisplayBox("We have analyzed the data from the RAM bank and can now create one. Go ahead and select the Platform here and construct one.");
if(box.bPressed){
state=2;
box.SetVisible(false);
flags.playerInControl=true;
}
}break;
case 2:{
for(auto&u:units){
if(u->IsRAMBank()&&u->IsFriendly()){
state=3;
flags.playerInControl=false;
SetObjective("");
break;
}
}
}break;
case 3:{
DisplayBox("Excellent, each RAM bank has the capability to allocate memory into the system. See that indicator down below?");
flags.flashMemoryBar=true;
if(box.bPressed){
state=4;
}
}break;
case 4:{
DisplayBox("This sector lets us allocate 30 bytes of RAM. That's 240 bits for the savvy folks out there.");
if(box.bPressed){
state=5;
flags.flashMemoryBar=false;
}
}break;
case 5:{
DisplayBox("Some of it has already been used up by our RAM bank and other system resources... ");
if(box.bPressed){
state=6;
}
}break;
case 6:{
SetObjective("Build a Memory Allocator.");
DisplayBox("To allocate 5 bits, select the RAM bank and click the Memory Allocator button.\n\nGive it a try now.");
if(box.bPressed){
state=7;
box.SetVisible(false);
flags.playerInControl=true;
}
}break;
case 7:{
for(auto&u:units){
if(u->IsAllocator()&&u->IsFriendly()){
state=8;
flags.playerInControl=false;
SetObjective("");
break;
}
}
}break;
case 8:{
SetObjective("Build a Left or Right Bit Shifter.");
DisplayBox("Now select the memory allocator and let's make a Shifter unit.");
if(box.bPressed){
state=9;
box.SetVisible(false);
flags.playerInControl=true;
}
}break;
case 9:{
for(auto&u:units){
if(!u->IsAllocator()&&!u->IsRAMBank()&&u->IsFriendly()){
state=10;
flags.playerInControl=false;
SetObjective("");
break;
}
}
}break;
case 10:{
DisplayBox("The memory shifters will be your primary way to delete memory from units.");
if(box.bPressed){
state=11;
SOUNDS[Sound::ALARM]->PlayCentered();
}
}break;
case 11:{
SetCameraTarget({22*24,23*24});
RevealTiles({22*24,23*24});
if(camera.ReachedTarget()){
state=12;
}
}break;
case 12:{
SetObjective("Defeat all enemy units.");
DisplayBox("I have detected viruses in the system again. Please eradicate them and free system resources.");
if(box.bPressed){
state=13;
flags.playerInControl=true;
box.SetVisible(false);
}
}break;
}
};
bool Stage2::MissionCompleted(){
for(auto&u:units){
if(!u->IsFriendly()){
return false;
}
}
return true;
}
Stage3::Stage3(std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_ptr<Renderable>>&IMAGES,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::string&objective,TileTransformedView&game,GameFlags&flags)
:Scenario(units,IMAGES,SOUNDS,objective,game,flags){}
void Stage3::Start(){
flags.playerInControl=false;
flags.unitMetersGreyedOut=true;
flags.guideEnabled=false;
flags.limitedBuildOptions=true;
SetCameraTarget({3*24,6*24},true);
oopsTimer=0.3;
nextLevel=LevelName::STAGE4;
};
void Stage3::Update(){
switch(state){
case 0:{
DisplayBox("I haven't touched on what the other meters on your units are, but they are important!");
if(box.bPressed){
SOUNDS[Sound::SWITCH]->PlayCentered();
flags.unitMetersGreyedOut=false;
state=1;
}
}break;
case 1:{
DisplayBox("The Blue bits indicates movement capabilities of a unit.");
if(box.bPressed){
state=2;
}
}break;
case 2:{
DisplayBox("The Green bits indicates the range of a unit.");
if(box.bPressed){
state=3;
}
}break;
case 3:{
DisplayBox("The Red bits are the attack speed bits.");
if(box.bPressed){
state=4;
}
}break;
case 4:{
DisplayBox("And Purple are the Procedure bits. Without these, your unit will fail to recall how to function.");
if(box.bPressed){
state=5;
}
}break;
case 5:{
DisplayBox("As units attack each other, their bits are going to get shuffled around, impeding their ability to perform.");
if(box.bPressed){
state=6;
}
}break;
case 6:{
DisplayBox("Your immediate goal is to always take out the Yellow bits but sometimes taking out other bits is important too.");
if(box.bPressed){
SOUNDS[Sound::SWITCH]->PlayCentered();
flags.guideEnabled=true;
state=7;
}
}break;
case 7:{
DisplayBox("I'll leave a guide by the map in case your memory betrays you.");
if(box.bPressed){
state=8;
}
}break;
case 8:{
SetObjective("Defeat all units");
DisplayBox("You now have access to more units as well. Do check them out!");
if(box.bPressed){
SetObjective("Defeat all units (Oops)");
state=9;
}
}break;
case 9:{
oopsTimer=std::max(0.f,oopsTimer-game.GetPGE()->GetElapsedTime());
if(oopsTimer==0){
SetObjective("Defeat all enemy units.");
state=10;
flags.limitedBuildOptions=false;
flags.playerInControl=true;
box.SetVisible(false);
}
}break;
case 10:{
}break;
}
};
bool Stage3::MissionCompleted(){
for(auto&u:units){
if(!u->IsFriendly()){
return false;
}
}
return true;
}
Stage4::Stage4(std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_ptr<Renderable>>&IMAGES,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::string&objective,TileTransformedView&game,GameFlags&flags)
:Scenario(units,IMAGES,SOUNDS,objective,game,flags){}
void Stage4::Start(){
nextLevel=LevelName::STAGE5;
flags.playerInControl=false;
flags.guideEnabled=true;
flags.limitedBuildOptions=false;
flags.unitMetersGreyedOut=false;
flags.flashMemoryBar=false;
SetCameraTarget({4*24,4*24},true);
};
void Stage4::Update(){
switch(state){
case 0:{
DisplayBox("Hacker, I have unfortunate news. I can't supply you with any more bits to construct things with.");
if(box.bPressed){
state=1;
}
}break;
case 1:{
DisplayBox("You've only got 3 health bits to start with this time. To allocate memory you always need at least 5 bits of memory.");
if(box.bPressed){
state=2;
}
}break;
case 2:{
SetCameraTarget({8*24,1*24});
if(camera.ReachedTarget()){
state=3;
}
}break;
case 3:{
DisplayBox("But we can collect bits from the system using these collection points.");
if(box.bPressed){
state=4;
}
}break;
case 4:{
DisplayBox("Simply bring over any unit to these and attach them to it. They will start providing you with system resources to make what you need.");
if(box.bPressed){
state=5;
}
}break;
case 5:{
flags.flashMemoryBar=true;
SetObjective("Setup units at collection points");
DisplayBox("Remember that the system has limited memory available. You'll always be fighting for free space from the system.");
if(box.bPressed){
state=6;
box.SetVisible(false);
flags.playerInControl=true;
}
}break;
case 6:{
collectorsAttached=0;
for(auto&u:units){
if(u->IsAttached()){
collectorsAttached++;
}
}
if(collectorsAttached>=2){
std::shared_ptr<Unit>target;
for(auto&u:units){
if(u->IsRAMBank()){
target=u;
}
}
state=7;
SOUNDS[Sound::ALARM]->PlayCentered();
flags.playerInControl=false;
auto u1=std::make_shared<LeftShifter>(game.GetPGE(),vf2d{4*24,10*24},IMAGES,false);
auto u2=std::make_shared<LeftShifter>(game.GetPGE(),vf2d{4*24,10*24},IMAGES,false);
auto u3=std::make_shared<LeftShifter>(game.GetPGE(),vf2d{4*24,10*24},IMAGES,false);
units.push_back(u1);
units.push_back(u2);
units.push_back(u3);
u1->SetTargetUnit(target);
u2->SetTargetUnit(target);
u3->SetTargetUnit(target);
}
}break;
case 7:{
SetCameraTarget({4*24,4*24});
if(camera.ReachedTarget()){
state=8;
SOUNDS[Sound::WIND]->PlayCentered();
}
}break;
case 8:{
DisplayBox("An ambush...? I, WHAT? -- THIS IS NOT-");
if(box.bPressed){
state=9;
box.SetVisible(false);
nextLevelTimer=5;
}
}break;
case 9:{
nextLevelTimer=std::max(0.f,nextLevelTimer-game.GetPGE()->GetElapsedTime());
if(nextLevelTimer==0){
state=10;
}
}break;
case 10:{
transitionToNextLevel=true;
state=11;
}break;
}
};
bool Stage4::MissionCompleted(){
return false;
}
Stage5::Stage5(std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_ptr<Renderable>>&IMAGES,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::string&objective,TileTransformedView&game,GameFlags&flags)
:Scenario(units,IMAGES,SOUNDS,objective,game,flags){}
void Stage5::Start(){
SetCameraTarget({4*24,4*24},true);
flags.playerInControl=true;
SetObjective("Defeat all enemy RAM banks.");
nextLevel=LevelName::STAGE6;
};
void Stage5::Update(){
switch(state){
case 0:{
}break;
}
};
bool Stage5::MissionCompleted(){
for(auto&u:units){
if(!u->IsFriendly()&&u->IsRAMBank()){
return false;
}
}
return true;
}
Stage6::Stage6(std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_ptr<Renderable>>&IMAGES,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::string&objective,TileTransformedView&game,GameFlags&flags)
:Scenario(units,IMAGES,SOUNDS,objective,game,flags){}
void Stage6::Start(){
SetCameraTarget({4*24,4*24},true);
flags.playerInControl=true;
SetObjective("Defeat all enemy RAM banks.");
nextLevel=LevelName::STAGE7;
};
void Stage6::Update(){
switch(state){
case 0:{
flags.playerInControl=false;
DisplayBox("...");
if(box.bPressed){
flags.playerInControl=true;
box.SetVisible(false);
}
}break;
}
};
bool Stage6::MissionCompleted(){
for(auto&u:units){
if(!u->IsFriendly()&&u->IsRAMBank()){
return false;
}
}
return true;
}
Stage7::Stage7(std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_ptr<Renderable>>&IMAGES,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::string&objective,TileTransformedView&game,GameFlags&flags)
:Scenario(units,IMAGES,SOUNDS,objective,game,flags){}
void Stage7::Start(){
SetCameraTarget({4*24,4*24},true);
flags.playerInControl=true;
SetObjective("Defeat all enemy units.");
nextLevel=LevelName::STAGE8;
};
void Stage7::Update(){
switch(state){
case 0:{
flags.playerInControl=false;
DisplayBox("I see you have a few new tricks up your sleeve, Hacker.");
if(box.bPressed){
state=1;
}
}break;
case 1:{
DisplayBox("Don't think it'll be that easy to get through this one...");
if(box.bPressed){
state=2;
flags.playerInControl=true;
box.SetVisible(false);
}
}break;
}
};
bool Stage7::MissionCompleted(){
for(auto&u:units){
if(!u->IsFriendly()){
return false;
}
}
return true;
}
Stage8::Stage8(std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_ptr<Renderable>>&IMAGES,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::string&objective,TileTransformedView&game,GameFlags&flags)
:Scenario(units,IMAGES,SOUNDS,objective,game,flags){}
void Stage8::Start(){
SetCameraTarget({4*24,4*24},true);
flags.playerInControl=true;
SetObjective("Defeat all enemy units.");
nextLevel=LevelName::FINISH;
};
void Stage8::Update(){
switch(state){
case 0:{
}break;
}
};
bool Stage8::MissionCompleted(){
for(auto&u:units){
if(!u->IsFriendly()){
return false;
}
}
return true;
}