Implemented Concussive Trap enchant.
This commit is contained in:
		
							parent
							
								
									9005771f77
								
							
						
					
					
						commit
						60175a20d2
					
				| @ -974,5 +974,42 @@ namespace EnchantTests | ||||
| 			} | ||||
| 			Assert::AreEqual(size_t(1),newMonster.GetBuffs(BuffType::SPECIAL_MARK).size(),L"A special mark should spawned with the enchant."); | ||||
| 		} | ||||
| 		TEST_METHOD(ConcussiveTrapEnchantCheck){ | ||||
| 			testKey->bHeld=true; //Force the key to be held down for testing purposes.
 | ||||
| 			game->ChangePlayerClass(TRAPPER); | ||||
| 			player=game->GetPlayer(); | ||||
| 			player->SetPos({120,120}); | ||||
| 			player->CheckAndPerformAbility(player->GetAbility3(),testKeyboardInput); | ||||
| 			game->SetElapsedTime(0.5f); | ||||
| 			game->OnUserUpdate(0.5f); | ||||
| 			Assert::AreEqual(size_t(1),BULLET_LIST.size(),L"An Explosive Trap now exists"); | ||||
| 			Monster&newMonster{game->SpawnMonster({},MONSTER_DATA["TestName"])}; | ||||
| 			game->OnUserUpdate(0.f); | ||||
| 			BULLET_LIST.front()->MonsterHit(newMonster,newMonster.GetMarkStacks()); | ||||
| 			Assert::AreEqual(929,newMonster.GetHealth(),L"Monster takes 71 damage from an Explosive Trap normally."); | ||||
| 			game->SetElapsedTime(5.5f); | ||||
| 			game->OnUserUpdate(5.5f); | ||||
| 			game->SetElapsedTime(5.5f); | ||||
| 			game->OnUserUpdate(5.5f); | ||||
| 			game->SetElapsedTime(0.5f); | ||||
| 			game->OnUserUpdate(0.5f); | ||||
| 			Assert::AreEqual(size_t(0),BULLET_LIST.size(),L"An Explosive Trap is gone."); | ||||
| 
 | ||||
| 			std::weak_ptr<Item>nullRing{Inventory::AddItem("Null Ring"s)}; | ||||
| 			Inventory::EquipItem(nullRing,EquipSlot::RING1); | ||||
| 			nullRing.lock()->EnchantItem("Concussive Trap"); | ||||
| 			player->GetAbility3().charges=1; | ||||
| 			player->CheckAndPerformAbility(player->GetAbility3(),testKeyboardInput); | ||||
| 			game->SetElapsedTime(0.5f); | ||||
| 			game->OnUserUpdate(0.5f); | ||||
| 			Assert::AreEqual(size_t(1),BULLET_LIST.size(),L"An Explosive Trap now exists"); | ||||
| 			game->SetElapsedTime(5.5f); | ||||
| 			game->OnUserUpdate(5.5f); | ||||
| 			Assert::AreEqual(size_t(1),BULLET_LIST.size(),L"An Explosive Trap still exists (in the process of detonating a few times)"); | ||||
| 			Assert::AreEqual(721,newMonster.GetHealth(),L"Monster takes 104 + 104 damage from Concussive Trap bonus (Collision+Collateral Explosion)."); | ||||
| 			game->SetElapsedTime(5.5f); | ||||
| 			game->OnUserUpdate(5.5f); | ||||
| 			Assert::AreEqual(size_t(0),BULLET_LIST.size(),L"Explosive Trap detonates later."); | ||||
| 		} | ||||
| 	}; | ||||
| } | ||||
|  | ||||
| @ -79,6 +79,7 @@ namespace ItemTests | ||||
| 			GameState::Initialize(); | ||||
| 			GameState::STATE=GameState::states.at(States::State::GAME_RUN); | ||||
| 			 | ||||
| 			testGame->ResetLevelStates(); | ||||
| 			#pragma region Setup a fake test map and test monster | ||||
| 				game->MAP_DATA["CAMPAIGN_1_1"]; | ||||
| 				ItemDrop::ClearDrops(); | ||||
|  | ||||
| @ -82,6 +82,7 @@ namespace MonsterTests | ||||
| 
 | ||||
| 			GameState::Initialize(); | ||||
| 			GameState::STATE=GameState::states.at(States::State::GAME_RUN); | ||||
| 			testGame->ResetLevelStates(); | ||||
| 			 | ||||
| 			#pragma region Setup a fake test map | ||||
| 				game->MAP_DATA["CAMPAIGN_1_1"]; | ||||
|  | ||||
| @ -88,6 +88,7 @@ namespace PlayerTests | ||||
| 				MonsterData testMonsterData{"TestName","Test Monster",1000,10,5,{MonsterDropData{"Health Potion",100.f,1,1}},200.f}; | ||||
| 				MONSTER_DATA["TestName"]=testMonsterData; | ||||
| 			#pragma endregion | ||||
| 			testGame->ResetLevelStates(); | ||||
| 
 | ||||
| 			player=testGame->GetPlayer(); | ||||
| 			//Setup key "0" as a test input
 | ||||
|  | ||||
| @ -188,7 +188,7 @@ AiL::AiL(bool testingMode){ | ||||
| 
 | ||||
| void InitializeGameConfigurations(){ | ||||
| 	DATA.Reset(); | ||||
| 
 | ||||
| 	 | ||||
| 	utils::datafile::Read(DATA,"assets/config/configuration.txt"); | ||||
| 
 | ||||
| 	utils::datafile::DEBUG_ACCESS_OPTIONS="debug_access_options"_I; | ||||
| @ -2387,55 +2387,7 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){ | ||||
| 				} | ||||
| 			#pragma endregion | ||||
| 
 | ||||
| 			bossIndicatorPos.reset(); | ||||
| 			SPAWNER_LIST.clear(); | ||||
| 			SPAWNER_CONTROLLER={}; | ||||
| 			foregroundTileGroups.clear(); | ||||
| 			upperForegroundTileGroups.clear(); | ||||
| 			MONSTER_LIST.clear(); | ||||
| 			BULLET_LIST.clear(); | ||||
| 			DAMAGENUMBER_LIST.clear(); | ||||
| 			hudOverlay.Reset(); | ||||
| 			backgroundEffects.clear(); | ||||
| 			foregroundEffects.clear(); | ||||
| 			lockOnTargets.clear(); | ||||
| 			lockOnSpecialTargets.clear(); | ||||
| 			ItemDrop::drops.clear(); | ||||
| 			GameEvent::events.clear(); | ||||
| 			Audio::SetBGMPitch(1.f); | ||||
| 			RepeatingSoundEffect::StopAllSounds(); | ||||
| 			#ifdef __EMSCRIPTEN__ | ||||
| 				Audio::muted=true; | ||||
| 				Audio::UpdateBGMVolume(); | ||||
| 			#endif | ||||
| 			zoomAdjustSpeed="Default Zoom Adjust Speed"_F; | ||||
| 			targetZoom=1.f; | ||||
| 			game->view.SetZoom(0.95f,game->view.WorldToScreen(game->camera.GetViewPosition())); | ||||
| 			worldColor=WHITE; | ||||
| 			worldColorFunc=[&](vi2d pos){return game->worldColor;}; | ||||
| 			levelTime=0; | ||||
| 			bossName=""; | ||||
| 			bossDisplayTimer=0.f; | ||||
| 			worldShakeTime=0.f; | ||||
| 			encounterDuration=0; | ||||
| 			totalDamageDealt=0; | ||||
| 			encounterStarted=false; | ||||
| 			totalBossEncounterMobs=0; | ||||
| 			SetWindSpeed({}); | ||||
| 			Inventory::ResetLoadoutItemsUsed(); | ||||
| 			Input::StopVibration(); | ||||
| 
 | ||||
| 			Input::SetLightbar({255,0,255}); | ||||
| 			GetPlayer()->hp=GetPlayer()->GetMaxHealth(); | ||||
| 			GetPlayer()->mana=GetPlayer()->GetMaxMana(); | ||||
| 			GetPlayer()->SetState(State::NORMAL); | ||||
| 			GetPlayer()->GetCastInfo()={}; | ||||
| 			GetPlayer()->ResetAccumulatedXP(); | ||||
| 			GetPlayer()->_SetIframes(0.f); | ||||
| 			GetPlayer()->SetInvisible(false); | ||||
| 			GetPlayer()->ResetVelocity(); | ||||
| 			GetPlayer()->RemoveAllBuffs(); | ||||
| 			GetPlayer()->ResetTimers(); | ||||
| 			ResetLevelStates(); | ||||
| 
 | ||||
| 			STEAMINPUT( //This is kind of a hack to refresh the in-game controls handle and button icons if for some reason it's not setup correctly.
 | ||||
| 				Input::LoadSteamButtonIcons(); | ||||
| @ -4618,4 +4570,56 @@ void AiL::InitializeCamera(){ | ||||
| 	camera.SetMode(olc::utils::Camera2D::Mode::LazyFollow); | ||||
| 	camera.SetWorldBoundary({0,0},GetCurrentMap().MapData.MapSize*GetCurrentMap().MapData.TileSize); | ||||
| 	camera.EnableWorldBoundary(false); | ||||
| } | ||||
| 
 | ||||
| void AiL::ResetLevelStates(){ | ||||
| 	bossIndicatorPos.reset(); | ||||
| 	SPAWNER_LIST.clear(); | ||||
| 	SPAWNER_CONTROLLER={}; | ||||
| 	foregroundTileGroups.clear(); | ||||
| 	upperForegroundTileGroups.clear(); | ||||
| 	MONSTER_LIST.clear(); | ||||
| 	BULLET_LIST.clear(); | ||||
| 	DAMAGENUMBER_LIST.clear(); | ||||
| 	hudOverlay.Reset(); | ||||
| 	backgroundEffects.clear(); | ||||
| 	foregroundEffects.clear(); | ||||
| 	lockOnTargets.clear(); | ||||
| 	lockOnSpecialTargets.clear(); | ||||
| 	ItemDrop::drops.clear(); | ||||
| 	GameEvent::events.clear(); | ||||
| 	Audio::SetBGMPitch(1.f); | ||||
| 	RepeatingSoundEffect::StopAllSounds(); | ||||
| 	#ifdef __EMSCRIPTEN__ | ||||
| 		Audio::muted=true; | ||||
| 		Audio::UpdateBGMVolume(); | ||||
| 	#endif | ||||
| 	zoomAdjustSpeed="Default Zoom Adjust Speed"_F; | ||||
| 	targetZoom=1.f; | ||||
| 	game->view.SetZoom(0.95f,game->view.WorldToScreen(game->camera.GetViewPosition())); | ||||
| 	worldColor=WHITE; | ||||
| 	worldColorFunc=[&](vi2d pos){return game->worldColor;}; | ||||
| 	levelTime=0; | ||||
| 	bossName=""; | ||||
| 	bossDisplayTimer=0.f; | ||||
| 	worldShakeTime=0.f; | ||||
| 	encounterDuration=0; | ||||
| 	totalDamageDealt=0; | ||||
| 	encounterStarted=false; | ||||
| 	totalBossEncounterMobs=0; | ||||
| 	SetWindSpeed({}); | ||||
| 	Inventory::ResetLoadoutItemsUsed(); | ||||
| 	Input::StopVibration(); | ||||
| 
 | ||||
| 	Input::SetLightbar({255,0,255}); | ||||
| 	GetPlayer()->hp=GetPlayer()->GetMaxHealth(); | ||||
| 	GetPlayer()->mana=GetPlayer()->GetMaxMana(); | ||||
| 	GetPlayer()->SetState(State::NORMAL); | ||||
| 	GetPlayer()->GetCastInfo()={}; | ||||
| 	GetPlayer()->ResetAccumulatedXP(); | ||||
| 	GetPlayer()->_SetIframes(0.f); | ||||
| 	GetPlayer()->SetInvisible(false); | ||||
| 	GetPlayer()->ResetVelocity(); | ||||
| 	GetPlayer()->RemoveAllBuffs(); | ||||
| 	GetPlayer()->ResetTimers(); | ||||
| } | ||||
| @ -394,6 +394,8 @@ public: | ||||
| 	void _SetCurrentLevel(const MapName map); //NOTE: This will modify the currentLevel variable without triggering anything else in-game, this will normally mess up the state in the game. Ideally this is only used when initializing a test level.
 | ||||
| 	void InitializeCamera(); | ||||
| 
 | ||||
| 	void ResetLevelStates(); | ||||
| 
 | ||||
| 	std::vector<Effect*>GetForegroundEffects()const; | ||||
| 	std::vector<Effect*>GetBackgroundEffects()const; | ||||
| 	std::vector<Effect*>GetAllEffects()const; //Foreground and background effects in one vector.
 | ||||
|  | ||||
| @ -61,6 +61,7 @@ enum BuffType{ | ||||
| 	DAMAGE_AMPLIFICATION, //Multiplies all incoming damage by this amount.
 | ||||
| 	LETHAL_TEMPO, | ||||
| 	BURNING_ARROW_BURN, | ||||
| 	SWORD_ENCHANTMENT, | ||||
| }; | ||||
| enum class BuffRestorationType{ | ||||
| 	ONE_OFF, //This is used as a hack fix for the RestoreDuringCast Item script since they require us to restore 1 tick immediately. Over time buffs do not apply a tick immediately.
 | ||||
|  | ||||
| @ -318,6 +318,8 @@ private: | ||||
| 	float automaticDetonationTime{}; | ||||
| 	float activationWaitTime{}; | ||||
| 	float lastBeepTime{}; | ||||
| 	int explosionCount{1}; | ||||
| 	float rearmTime{}; | ||||
| 	uint8_t beepCount{1U}; | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -47,7 +47,7 @@ INCLUDE_ANIMATION_DATA | ||||
| INCLUDE_game | ||||
| 
 | ||||
| ExplosiveTrap::ExplosiveTrap(vf2d pos,float radius,float explosionRadius,float automaticDetonationTime,int damage,float fadeinTime,float fadeoutTime,float activationWaitTime,bool upperLevel,bool hitsMultiple,float lifetime,bool friendly,Pixel col,vf2d scale) | ||||
| 	:activationWaitTime(activationWaitTime),automaticDetonationTime(automaticDetonationTime),activationRadius(radius),explosionRadius(explosionRadius),Bullet(pos,{},0.f,damage,"Ability Icons/explosive_trap.png",upperLevel,hitsMultiple,lifetime,false,friendly,col,scale,0.f,"Trap Hit"){ | ||||
| 	:activationWaitTime(activationWaitTime),automaticDetonationTime(automaticDetonationTime),activationRadius(radius),explosionRadius(explosionRadius),explosionCount(game->GetPlayer()->HasEnchant("Concussive Trap")?"Concussive Trap"_ENC["TRAP EXPLODE COUNT"]:1),Bullet(pos,{},0.f,damage,"Ability Icons/explosive_trap.png",upperLevel,hitsMultiple,INFINITE,false,friendly,col,scale,0.f,"Trap Hit"){ | ||||
| 	fadeInTime=fadeinTime; | ||||
| 	animation.AddState("explosive_trap.png",ANIMATION_DATA["explosive_trap.png"]); | ||||
| 	if(!friendly)ERR("WARNING! Trying to use unimplemented enemy version of the Explosive Trap Bullet!"); | ||||
| @ -58,7 +58,10 @@ void ExplosiveTrap::Update(float fElapsedTime){ | ||||
| 
 | ||||
| 	if(IsDeactivated())return; | ||||
| 
 | ||||
| 	if(!trapActivated){ | ||||
| 	if(rearmTime>0.f){ | ||||
| 		rearmTime-=fElapsedTime; | ||||
| 		if(rearmTime<=0.f)Detonate(); | ||||
| 	}else if(!trapActivated){ | ||||
| 		activationWaitTime-=fElapsedTime; | ||||
| 		if(activationWaitTime<=0.f){ | ||||
| 			radius=activationRadius; | ||||
| @ -89,8 +92,7 @@ BulletDestroyState ExplosiveTrap::PlayerHit(Player*player){ | ||||
| } | ||||
| 
 | ||||
| void ExplosiveTrap::Detonate(){ | ||||
| 	fadeOutTime=0.5f; | ||||
| 	const HurtList list{game->HurtNotHit(pos,"Trapper.Ability 3.Explosion Radius"_F/100.f*24,damage,hitList,OnUpperLevel(),GetZ(),HurtType::MONSTER,HurtFlag::PLAYER_ABILITY)}; | ||||
| 	const HurtList list{game->Hurt(pos,"Trapper.Ability 3.Explosion Radius"_F/100.f*24,damage,OnUpperLevel(),GetZ(),HurtType::MONSTER,HurtFlag::PLAYER_ABILITY)}; | ||||
| 	for(const auto&[targetPtr,wasHit]:list){ | ||||
| 		if(wasHit){ | ||||
| 			std::get<Monster*>(targetPtr)->ApplyMark("Trapper.Ability 3.Explosion Mark Stack Time"_F,"Trapper.Ability 3.Explosion Mark Stack Increase"_I); | ||||
| @ -103,7 +105,13 @@ void ExplosiveTrap::Detonate(){ | ||||
| 	explodeEffect->scaleSpd={0.125f,0.125f}; | ||||
| 	game->AddEffect(std::move(explodeEffect)); | ||||
| 	SoundEffect::PlaySFX("Explosion",pos); | ||||
| 	Deactivate(); | ||||
| 	explosionCount--; | ||||
| 	if(explosionCount>0)rearmTime=0.6f; | ||||
| 	else{ | ||||
| 		fadeOutTime=0.5f; | ||||
| 		Deactivate(); | ||||
| 		lifetime=0.f; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| BulletDestroyState ExplosiveTrap::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit){ | ||||
|  | ||||
| @ -335,6 +335,7 @@ float Player::GetSizeMult()const{ | ||||
| float Player::GetAttackRange(){ | ||||
| 	float finalAttackRange{base_attack_range}; | ||||
| 	if(HasEnchant("Adrenaline Stim")&&GetBuffs(BuffType::ADRENALINE_RUSH).size()>0)finalAttackRange+=base_attack_range*"Adrenaline Stim"_ENC["ATTACK RANGE INCREASE PCT"]/100.f; | ||||
| 	if(GetBuffs(BuffType::SWORD_ENCHANTMENT).size()>0)finalAttackRange+=base_attack_range*"Sword Enchantment"_ENC["AUTO RANGE INCREASE"]/100.f; | ||||
| 	finalAttackRange*=GetSizeMult(); | ||||
| 	return finalAttackRange; | ||||
| } | ||||
|  | ||||
| @ -126,7 +126,9 @@ void Trapper::InitializeClassAbilities(){ | ||||
| 	#pragma region Trapper Ability 3 (Explosive Trap) | ||||
| 		Trapper::ability3.action= | ||||
| 			[](Player*p,vf2d pos={}){ | ||||
| 				CreateBullet(ExplosiveTrap)(p->GetPos(),"Trapper.Ability 3.Trap Radius"_I,"Trapper.Ability 3.Explosion Radius"_F/100.f*24,"Trapper.Ability 3.Trap Auto Detonate Time"_F,"Trapper.Ability 3.DamageMult"_F*p->GetAttack(),0.2f,0.5f,"Trapper.Ability 3.Trap Activation Time"_F,p->OnUpperLevel(),false,INFINITE,true,WHITE,{1.f,1.f})EndBullet; | ||||
| 				float trapDamage{"Trapper.Ability 3.DamageMult"_F*p->GetAttack()}; | ||||
| 				if(p->HasEnchant("Concussive Trap"))trapDamage+=p->GetAttack()*"Concussive Trap"_ENC["ADDITIONAL EXPLOSION DAMAGE"]/100.f; | ||||
| 				CreateBullet(ExplosiveTrap)(p->GetPos(),"Trapper.Ability 3.Trap Radius"_I,"Trapper.Ability 3.Explosion Radius"_F/100.f*24,"Trapper.Ability 3.Trap Auto Detonate Time"_F,trapDamage,0.2f,0.5f,"Trapper.Ability 3.Trap Activation Time"_F,p->OnUpperLevel(),false,INFINITE,true,WHITE,{1.f,1.f})EndBullet; | ||||
| 				SoundEffect::PlaySFX("Place Down Trap",p->GetPos()); | ||||
| 				p->SetAnimationBasedOnTargetingDirection("SETTRAP",p->GetFacingDirection()); | ||||
| 				return true; | ||||
|  | ||||
| @ -39,7 +39,7 @@ All rights reserved. | ||||
| #define VERSION_MAJOR 1 | ||||
| #define VERSION_MINOR 2 | ||||
| #define VERSION_PATCH 3 | ||||
| #define VERSION_BUILD 11039 | ||||
| #define VERSION_BUILD 11048 | ||||
| 
 | ||||
| #define stringify(a) stringify_(a) | ||||
| #define stringify_(a) #a | ||||
|  | ||||
| @ -168,6 +168,7 @@ void Warrior::InitializeClassAbilities(){ | ||||
| 				} | ||||
| 				BULLET_LIST.push_back(std::make_unique<Bullet>(p->GetPos(),bulletVel,"Warrior.Ability 3.Radius"_F,p->GetAttack()*"Warrior.Ability 3.DamageMult"_F,"sonicslash.png",p->upperLevel,true,"Warrior.Ability 3.Lifetime"_F,true,true,WHITE,vf2d{"Warrior.Ability 3.Radius"_F/30,"Warrior.Ability 3.Radius"_F/30})); | ||||
| 				game->SetupWorldShake("Warrior.Ability 3.ShakeTime"_F); | ||||
| 				if(p->HasEnchant("Sword Enchantment"))p->AddBuff(BuffType::SWORD_ENCHANTMENT,"Sword Enchantment"_ENC["INCREASE DURATION"],1); | ||||
| 				SoundEffect::PlaySFX("Warrior Sonic Slash",SoundEffect::CENTERED); | ||||
| 				return true; | ||||
| 			}; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user