| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | #include "Scenario.h"
 | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | #include "TileManager.h"
 | 
					
						
							| 
									
										
										
										
											2023-09-03 13:25:35 -05:00
										 |  |  | #include "olcUTIL_Geometry2D.h"
 | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 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){} | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | Scenario::~Scenario(){}; | 
					
						
							|  |  |  | void Scenario::_Start(){ | 
					
						
							|  |  |  | 	state=0; | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 	camera=utils::Camera2D{game.GetPGE()->GetScreenSize(),game.GetWorldOffset()}; | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | 	camera.SetLazyFollowRate(2); | 
					
						
							|  |  |  | 	camera.SetMode(utils::Camera2D::Mode::LazyFollow); | 
					
						
							|  |  |  | 	targetPos={96,96}; | 
					
						
							|  |  |  | 	box.SetVisible(false); | 
					
						
							|  |  |  | 	initialWaitTime=3; | 
					
						
							|  |  |  | 	camera.SetTarget(targetPos); | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 	missionCompletedTimer=0; | 
					
						
							|  |  |  | 	transitionToNextLevel=false; | 
					
						
							| 
									
										
										
										
											2023-09-03 12:02:06 -05:00
										 |  |  | 	setupEasyMode=false; | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | 	Start(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void Scenario::Start(){}; | 
					
						
							| 
									
										
										
										
											2023-09-03 12:02:06 -05:00
										 |  |  | 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){ | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 	initialWaitTime=std::max(0.f,initialWaitTime-game.GetPGE()->GetElapsedTime()); | 
					
						
							|  |  |  | 	missionFinishWaitTime=std::max(0.f,missionFinishWaitTime-game.GetPGE()->GetElapsedTime()); | 
					
						
							| 
									
										
										
										
											2023-09-03 04:28:23 -05:00
										 |  |  | 	smallTimePass=std::min(1.f,smallTimePass+game.GetPGE()->GetElapsedTime()); | 
					
						
							|  |  |  | 	if(flags.playerInControl){ | 
					
						
							|  |  |  | 		smallTimePass=0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 	if(missionCompleted){ | 
					
						
							|  |  |  | 		missionCompletedTimer+=game.GetPGE()->GetElapsedTime(); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		missionCompleted=MissionCompleted(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-09-03 12:02:06 -05:00
										 |  |  | 	if(flags.playerInControl){ | 
					
						
							|  |  |  | 		RunAI(enemy_resources,collectionPoints,availableMemory,queuedUnits,SOUNDS); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | 	if(initialWaitTime==0){ | 
					
						
							|  |  |  | 		Update(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2023-09-03 12:02:06 -05:00
										 |  |  | 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}; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-09-03 14:16:01 -05:00
										 |  |  | 	attackTimer=std::max(0.f,attackTimer-game.GetPGE()->GetElapsedTime()); | 
					
						
							| 
									
										
										
										
											2023-09-03 12:02:06 -05:00
										 |  |  | 	unitBuildTimer=std::max(0.f,unitBuildTimer-game.GetPGE()->GetElapsedTime()); | 
					
						
							| 
									
										
										
										
											2023-09-03 13:25:35 -05:00
										 |  |  | 	std::weak_ptr<Unit>baseOfOperations; | 
					
						
							| 
									
										
										
										
											2023-09-03 14:16:01 -05:00
										 |  |  | 	std::weak_ptr<Unit>enemyBaseOfOperations; | 
					
						
							| 
									
										
										
										
											2023-09-03 13:25:35 -05:00
										 |  |  | 	for(auto&u:units){ | 
					
						
							|  |  |  | 		if(!u->IsFriendly()&&u->IsRAMBank()){ | 
					
						
							|  |  |  | 			baseOfOperations=u; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-09-03 14:16:01 -05:00
										 |  |  | 	for(auto&u:units){ | 
					
						
							|  |  |  | 		if(u->IsFriendly()&&u->IsRAMBank()){ | 
					
						
							|  |  |  | 			enemyBaseOfOperations=u; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-09-03 13:25:35 -05:00
										 |  |  | 	if(baseOfOperations.expired()){ | 
					
						
							|  |  |  | 		for(auto&u:units){ | 
					
						
							|  |  |  | 			if(!u->IsFriendly()){ | 
					
						
							|  |  |  | 				baseOfOperations=u; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-09-03 12:02:06 -05:00
										 |  |  | 	//See if there are collectors, if so send memory allocator units towards them.
 | 
					
						
							| 
									
										
										
										
											2023-09-03 13:25:35 -05:00
										 |  |  | 	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){ | 
					
						
							| 
									
										
										
										
											2023-09-03 12:02:06 -05:00
										 |  |  | 		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){ | 
					
						
							| 
									
										
										
										
											2023-09-03 14:16:01 -05:00
										 |  |  | 			if(!u->IsFriendly()&&u->IsRAMBank()){ | 
					
						
							| 
									
										
										
										
											2023-09-03 12:02:06 -05:00
										 |  |  | 				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; | 
					
						
							| 
									
										
										
										
											2023-09-03 13:25:35 -05:00
										 |  |  | 				for(int i=0;i<unitResourceCostList[randomIndex].size();i++){ | 
					
						
							| 
									
										
										
										
											2023-09-03 12:02:06 -05:00
										 |  |  | 					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); | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2023-09-03 15:54:32 -05:00
										 |  |  | 			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); | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2023-09-03 12:02:06 -05:00
										 |  |  | 			switch(flags.difficulty){ | 
					
						
							|  |  |  | 			case 0:{ | 
					
						
							|  |  |  | 				unitBuildTimer=120; | 
					
						
							|  |  |  | 			}break; | 
					
						
							|  |  |  | 			case 1:{ | 
					
						
							|  |  |  | 				unitBuildTimer=60; | 
					
						
							|  |  |  | 			}break; | 
					
						
							|  |  |  | 			case 2:{ | 
					
						
							|  |  |  | 				unitBuildTimer=10; | 
					
						
							|  |  |  | 			}break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-09-03 14:16:01 -05:00
										 |  |  | 	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; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-09-03 12:02:06 -05:00
										 |  |  | } | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  | 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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | bool Scenario::MissionCompleted(){return false;} | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | void Scenario::Update(){}; | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 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){ | 
					
						
							| 
									
										
										
										
											2023-09-03 03:28:04 -05:00
										 |  |  | 				transitionToNextLevel=true; | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	Resources temp={0,0,0,0,0}; | 
					
						
							|  |  |  | 	box.UpdateAndDraw({24,64},game.GetPGE(),temp,IMAGES,0,0); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-09-03 04:28:23 -05:00
										 |  |  | void Scenario::SetCameraTarget(vf2d pos,bool instant){ | 
					
						
							|  |  |  | 	if(instant){camera.SetMode(utils::Camera2D::Mode::Simple);} else {camera.SetMode(utils::Camera2D::Mode::LazyFollow);} | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 	targetPos=pos; | 
					
						
							|  |  |  | 	camera.SetTarget(targetPos); | 
					
						
							|  |  |  | 	camera.Update(game.GetPGE()->GetElapsedTime()); | 
					
						
							|  |  |  | 	game.SetWorldOffset(camera.GetViewPosition()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void Scenario::SetObjective(std::string objective){ | 
					
						
							|  |  |  | 	this->objective=objective; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-09-03 04:28:23 -05:00
										 |  |  | 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; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 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){} | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | void Stage1::Start(){ | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 	flags.unitMetersGreyedOut=true; | 
					
						
							|  |  |  | 	flags.playerInControl=false; | 
					
						
							|  |  |  | 	nextLevel=LevelName::STAGE2; | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | void Scenario::DisplayBox(std::string text,bool scaryHoodedFigure){ | 
					
						
							| 
									
										
										
										
											2023-09-03 04:28:23 -05:00
										 |  |  | 	if(smallTimePass==1){ | 
					
						
							|  |  |  | 		box.Initialize(text,{24,64},"",scaryHoodedFigure?IMAGES[SPOOK_HOODED_FIGURE].get():IMAGES[HOODED_FIGURE].get(),{378,28},SOUNDS[Sound::VOICEOVER].get()); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | void Stage1::Update(){ | 
					
						
							|  |  |  | 	switch(state){ | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 	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(); | 
					
						
							| 
									
										
										
										
											2023-09-03 04:28:23 -05:00
										 |  |  | 			RevealTiles({320,320}); | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	}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:{ | 
					
						
							| 
									
										
										
										
											2023-09-03 04:28:23 -05:00
										 |  |  | 		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."); | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 		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; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 	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(){ | 
					
						
							| 
									
										
										
										
											2023-09-03 04:28:23 -05:00
										 |  |  | 	flags.playerInControl=false; | 
					
						
							|  |  |  | 	flags.limitedBuildOptions=true; | 
					
						
							| 
									
										
										
										
											2023-09-03 06:24:12 -05:00
										 |  |  | 	flags.flashMemoryBar=false; | 
					
						
							|  |  |  | 	SetCameraTarget({7*24,10*24},true); | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 	nextLevel=LevelName::STAGE3; | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | }; | 
					
						
							|  |  |  | void Stage2::Update(){ | 
					
						
							|  |  |  | 	switch(state){ | 
					
						
							| 
									
										
										
										
											2023-09-03 04:28:23 -05:00
										 |  |  | 		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:{ | 
					
						
							| 
									
										
										
										
											2023-09-03 06:24:12 -05:00
										 |  |  | 			SetObjective("Create a RAM bank."); | 
					
						
							| 
									
										
										
										
											2023-09-03 04:28:23 -05:00
										 |  |  | 			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; | 
					
						
							| 
									
										
										
										
											2023-09-03 06:24:12 -05:00
										 |  |  | 					SetObjective(""); | 
					
						
							| 
									
										
										
										
											2023-09-03 04:28:23 -05:00
										 |  |  | 					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:{ | 
					
						
							| 
									
										
										
										
											2023-09-03 06:24:12 -05:00
										 |  |  | 			SetObjective("Build a Memory Allocator."); | 
					
						
							| 
									
										
										
										
											2023-09-03 04:28:23 -05:00
										 |  |  | 			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; | 
					
						
							| 
									
										
										
										
											2023-09-03 06:24:12 -05:00
										 |  |  | 					SetObjective(""); | 
					
						
							| 
									
										
										
										
											2023-09-03 04:28:23 -05:00
										 |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}break; | 
					
						
							|  |  |  | 		case 8:{ | 
					
						
							| 
									
										
										
										
											2023-09-03 06:24:12 -05:00
										 |  |  | 			SetObjective("Build a Left or Right Bit Shifter."); | 
					
						
							| 
									
										
										
										
											2023-09-03 04:28:23 -05:00
										 |  |  | 			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; | 
					
						
							| 
									
										
										
										
											2023-09-03 06:24:12 -05:00
										 |  |  | 					SetObjective(""); | 
					
						
							| 
									
										
										
										
											2023-09-03 04:28:23 -05:00
										 |  |  | 					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; | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | bool Stage2::MissionCompleted(){ | 
					
						
							| 
									
										
										
										
											2023-09-03 04:28:23 -05:00
										 |  |  | 	for(auto&u:units){ | 
					
						
							|  |  |  | 		if(!u->IsFriendly()){ | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return true; | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 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(){ | 
					
						
							| 
									
										
										
										
											2023-09-03 06:24:12 -05:00
										 |  |  | 	flags.playerInControl=false; | 
					
						
							|  |  |  | 	flags.unitMetersGreyedOut=true; | 
					
						
							|  |  |  | 	flags.guideEnabled=false; | 
					
						
							| 
									
										
										
										
											2023-09-03 07:13:05 -05:00
										 |  |  | 	flags.limitedBuildOptions=true; | 
					
						
							| 
									
										
										
										
											2023-09-03 06:24:12 -05:00
										 |  |  | 	SetCameraTarget({3*24,6*24},true); | 
					
						
							|  |  |  | 	oopsTimer=0.3; | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 	nextLevel=LevelName::STAGE4; | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | void Stage3::Update(){ | 
					
						
							|  |  |  | 	switch(state){ | 
					
						
							| 
									
										
										
										
											2023-09-03 06:24:12 -05:00
										 |  |  | 		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; | 
					
						
							| 
									
										
										
										
											2023-09-03 07:13:05 -05:00
										 |  |  | 				flags.limitedBuildOptions=false; | 
					
						
							| 
									
										
										
										
											2023-09-03 06:24:12 -05:00
										 |  |  | 				flags.playerInControl=true; | 
					
						
							| 
									
										
										
										
											2023-09-03 07:13:05 -05:00
										 |  |  | 				box.SetVisible(false); | 
					
						
							| 
									
										
										
										
											2023-09-03 06:24:12 -05:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		}break; | 
					
						
							|  |  |  | 		case 10:{ | 
					
						
							|  |  |  | 		}break; | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | bool Stage3::MissionCompleted(){ | 
					
						
							| 
									
										
										
										
											2023-09-03 06:24:12 -05:00
										 |  |  | 	for(auto&u:units){ | 
					
						
							|  |  |  | 		if(!u->IsFriendly()){ | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return true; | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 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; | 
					
						
							| 
									
										
										
										
											2023-09-03 13:25:35 -05:00
										 |  |  | 	flags.playerInControl=false; | 
					
						
							|  |  |  | 	flags.guideEnabled=true; | 
					
						
							|  |  |  | 	flags.limitedBuildOptions=false; | 
					
						
							|  |  |  | 	flags.unitMetersGreyedOut=false; | 
					
						
							|  |  |  | 	flags.flashMemoryBar=false; | 
					
						
							|  |  |  | 	SetCameraTarget({4*24,4*24},true); | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | void Stage4::Update(){ | 
					
						
							|  |  |  | 	switch(state){ | 
					
						
							| 
									
										
										
										
											2023-09-03 13:25:35 -05:00
										 |  |  | 		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; | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 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(){ | 
					
						
							| 
									
										
										
										
											2023-09-03 13:25:35 -05:00
										 |  |  | 	SetCameraTarget({4*24,4*24},true); | 
					
						
							|  |  |  | 	flags.playerInControl=true; | 
					
						
							|  |  |  | 	SetObjective("Defeat all enemy RAM banks."); | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 	nextLevel=LevelName::STAGE6; | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | void Stage5::Update(){ | 
					
						
							|  |  |  | 	switch(state){ | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 	case 0:{ | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 	}break; | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | bool Stage5::MissionCompleted(){ | 
					
						
							| 
									
										
										
										
											2023-09-03 13:25:35 -05:00
										 |  |  | 	for(auto&u:units){ | 
					
						
							|  |  |  | 		if(!u->IsFriendly()&&u->IsRAMBank()){ | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return true; | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 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(){ | 
					
						
							| 
									
										
										
										
											2023-09-03 13:25:35 -05:00
										 |  |  | 	SetCameraTarget({4*24,4*24},true); | 
					
						
							|  |  |  | 	flags.playerInControl=true; | 
					
						
							|  |  |  | 	SetObjective("Defeat all enemy RAM banks."); | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 	nextLevel=LevelName::STAGE7; | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | void Stage6::Update(){ | 
					
						
							|  |  |  | 	switch(state){ | 
					
						
							| 
									
										
										
										
											2023-09-03 14:16:01 -05:00
										 |  |  | 		case 0:{ | 
					
						
							|  |  |  | 			flags.playerInControl=false; | 
					
						
							|  |  |  | 			DisplayBox("..."); | 
					
						
							|  |  |  | 			if(box.bPressed){ | 
					
						
							|  |  |  | 				flags.playerInControl=true;	 | 
					
						
							|  |  |  | 				box.SetVisible(false); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}break; | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | bool Stage6::MissionCompleted(){ | 
					
						
							| 
									
										
										
										
											2023-09-03 13:25:35 -05:00
										 |  |  | 	for(auto&u:units){ | 
					
						
							|  |  |  | 		if(!u->IsFriendly()&&u->IsRAMBank()){ | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return true; | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 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(){ | 
					
						
							| 
									
										
										
										
											2023-09-03 13:25:35 -05:00
										 |  |  | 	SetCameraTarget({4*24,4*24},true); | 
					
						
							|  |  |  | 	flags.playerInControl=true; | 
					
						
							|  |  |  | 	SetObjective("Defeat all enemy units."); | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 	nextLevel=LevelName::STAGE8; | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | void Stage7::Update(){ | 
					
						
							|  |  |  | 	switch(state){ | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 	case 0:{ | 
					
						
							| 
									
										
										
										
											2023-09-03 14:16:01 -05:00
										 |  |  | 		flags.playerInControl=false; | 
					
						
							|  |  |  | 		DisplayBox("I see you have a few new tricks up your sleeve, Hacker."); | 
					
						
							|  |  |  | 		if(box.bPressed){ | 
					
						
							|  |  |  | 			state=1; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 	}break; | 
					
						
							| 
									
										
										
										
											2023-09-03 14:16:01 -05:00
										 |  |  | 		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; | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | bool Stage7::MissionCompleted(){ | 
					
						
							| 
									
										
										
										
											2023-09-03 13:25:35 -05:00
										 |  |  | 	for(auto&u:units){ | 
					
						
							|  |  |  | 		if(!u->IsFriendly()){ | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return true; | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 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(){ | 
					
						
							| 
									
										
										
										
											2023-09-03 13:25:35 -05:00
										 |  |  | 	SetCameraTarget({4*24,4*24},true); | 
					
						
							|  |  |  | 	flags.playerInControl=true; | 
					
						
							|  |  |  | 	SetObjective("Defeat all enemy units."); | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 	nextLevel=LevelName::FINISH; | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | void Stage8::Update(){ | 
					
						
							|  |  |  | 	switch(state){ | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 	case 0:{ | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | 	}break; | 
					
						
							| 
									
										
										
										
											2023-09-03 01:54:07 -05:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | }; | 
					
						
							|  |  |  | bool Stage8::MissionCompleted(){ | 
					
						
							| 
									
										
										
										
											2023-09-03 13:25:35 -05:00
										 |  |  | 	for(auto&u:units){ | 
					
						
							|  |  |  | 		if(!u->IsFriendly()){ | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return true; | 
					
						
							| 
									
										
										
										
											2023-09-03 03:22:04 -05:00
										 |  |  | } |