mirror of
				https://github.com/DarkflameUniverse/DarkflameServer.git
				synced 2025-10-31 12:41:55 +00:00 
			
		
		
		
	Merge remote-tracking branch 'upstream/main' into PetFixes
This commit is contained in:
		| @@ -4,8 +4,9 @@ include(CTest) | ||||
|  | ||||
| set(CMAKE_CXX_STANDARD 20) | ||||
| set(CXX_STANDARD_REQUIRED ON) | ||||
| set(CMAKE_POLICY_DEFAULT_CMP0063 NEW) # Set CMAKE visibility policy to NEW on project and subprojects | ||||
| set(CMAKE_CXX_VISIBILITY_PRESET hidden) # Set C++ symbol visibility to default to hidden | ||||
| set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 	# Export the compile commands for debugging | ||||
| set(CMAKE_POLICY_DEFAULT_CMP0063 NEW) 	# Set CMAKE visibility policy to NEW on project and subprojects | ||||
| set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) # Set C and C++ symbol visibility to hide inlined functions | ||||
| set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") | ||||
|  | ||||
| # Read variables from file | ||||
|   | ||||
| @@ -73,7 +73,7 @@ sudo apt install build-essential gcc zlib1g-dev libssl-dev openssl mariadb-serve | ||||
| ``` | ||||
|  | ||||
| #### Required CMake version | ||||
| This project uses <font size="4">**CMake version 3.18**</font> or higher and as such you will need to ensure you have this version installed. | ||||
| This project uses <font size="4">**CMake version 3.25**</font> or higher and as such you will need to ensure you have this version installed. | ||||
| You can check your CMake version by using the following command in a terminal. | ||||
| ```bash | ||||
| cmake --version | ||||
|   | ||||
| @@ -390,7 +390,7 @@ LWOOBJID PlayerContainer::GetId(const std::u16string& playerName) { | ||||
| } | ||||
|  | ||||
| PlayerData& PlayerContainer::GetPlayerDataMutable(const LWOOBJID& playerID) { | ||||
| 	return m_Players[playerID]; | ||||
| 	return m_Players.contains(playerID) ? m_Players[playerID] : m_Players[LWOOBJID_EMPTY]; | ||||
| } | ||||
|  | ||||
| PlayerData& PlayerContainer::GetPlayerDataMutable(const std::string& playerName) { | ||||
|   | ||||
| @@ -166,7 +166,7 @@ namespace GeneralUtils { | ||||
| 		return isParsed ? static_cast<T>(result) : std::optional<T>{}; | ||||
| 	} | ||||
|  | ||||
| #ifdef DARKFLAME_PLATFORM_MACOS | ||||
| #if !(__GNUC__ >= 11 || _MSC_VER >= 1924) | ||||
|  | ||||
| 	// MacOS floating-point parse helper function specializations | ||||
| 	namespace details { | ||||
|   | ||||
| @@ -731,15 +731,21 @@ void Entity::Initialize() { | ||||
| 		// if we have a moving platform path, then we need a moving platform component | ||||
| 		if (path->pathType == PathType::MovingPlatform) { | ||||
| 			AddComponent<MovingPlatformComponent>(pathName); | ||||
| 			// else if we are a movement path | ||||
| 		} /*else if (path->pathType == PathType::Movement) { | ||||
| 			auto movementAIcomp = GetComponent<MovementAIComponent>(); | ||||
| 			if (movementAIcomp){ | ||||
| 				// TODO: set path in existing movementAIComp | ||||
| 		} else if (path->pathType == PathType::Movement) { | ||||
| 			auto movementAIcomponent = GetComponent<MovementAIComponent>(); | ||||
| 			if (movementAIcomponent && combatAiId == 0) { | ||||
| 				movementAIcomponent->SetPath(pathName); | ||||
| 			} else { | ||||
| 				// TODO: create movementAIcomp and set path | ||||
| 				MovementAIInfo moveInfo = MovementAIInfo(); | ||||
| 				moveInfo.movementType = ""; | ||||
| 				moveInfo.wanderChance = 0; | ||||
| 				moveInfo.wanderRadius = 16; | ||||
| 				moveInfo.wanderSpeed = 2.5f; | ||||
| 				moveInfo.wanderDelayMax = 5; | ||||
| 				moveInfo.wanderDelayMin = 2; | ||||
| 				AddComponent<MovementAIComponent>(moveInfo); | ||||
| 			} | ||||
| 		}*/ | ||||
| 		} | ||||
| 	} else { | ||||
| 		// else we still need to setup moving platform if it has a moving platform comp but no path | ||||
| 		int32_t movingPlatformComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MOVING_PLATFORM, -1); | ||||
|   | ||||
| @@ -222,7 +222,7 @@ void BasicAttackBehavior::DoBehaviorCalculation(BehaviorContext* context, RakNet | ||||
| 		if (healthDamageDealt >= 1) { | ||||
| 			successState = eBasicAttackSuccessTypes::SUCCESS; | ||||
| 		} else if (armorDamageDealt >= 1) { | ||||
| 			successState = this->m_OnFailArmor->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY ? eBasicAttackSuccessTypes::FAILIMMUNE : eBasicAttackSuccessTypes::FAILARMOR; | ||||
| 			successState = this->m_OnFailArmor->m_templateId == BehaviorTemplate::EMPTY ? eBasicAttackSuccessTypes::FAILIMMUNE : eBasicAttackSuccessTypes::FAILARMOR; | ||||
| 		} | ||||
|  | ||||
| 		bitStream.Write(armorDamageDealt); | ||||
|   | ||||
| @@ -5,7 +5,7 @@ | ||||
| #include "CDActivitiesTable.h" | ||||
| #include "Game.h" | ||||
| #include "Logger.h" | ||||
| #include "BehaviorTemplates.h" | ||||
| #include "BehaviorTemplate.h" | ||||
| #include "BehaviorBranchContext.h" | ||||
| #include <unordered_map> | ||||
|  | ||||
| @@ -110,176 +110,176 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) { | ||||
| 	Behavior* behavior = nullptr; | ||||
|  | ||||
| 	switch (templateId) { | ||||
| 	case BehaviorTemplates::BEHAVIOR_EMPTY: break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_BASIC_ATTACK: | ||||
| 	case BehaviorTemplate::EMPTY: break; | ||||
| 	case BehaviorTemplate::BASIC_ATTACK: | ||||
| 		behavior = new BasicAttackBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_TAC_ARC: | ||||
| 	case BehaviorTemplate::TAC_ARC: | ||||
| 		behavior = new TacArcBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_AND: | ||||
| 	case BehaviorTemplate::AND: | ||||
| 		behavior = new AndBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_PROJECTILE_ATTACK: | ||||
| 	case BehaviorTemplate::PROJECTILE_ATTACK: | ||||
| 		behavior = new ProjectileAttackBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_HEAL: | ||||
| 	case BehaviorTemplate::HEAL: | ||||
| 		behavior = new HealBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_MOVEMENT_SWITCH: | ||||
| 	case BehaviorTemplate::MOVEMENT_SWITCH: | ||||
| 		behavior = new MovementSwitchBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_AREA_OF_EFFECT: | ||||
| 	case BehaviorTemplate::AREA_OF_EFFECT: | ||||
| 		behavior = new AreaOfEffectBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_PLAY_EFFECT: | ||||
| 	case BehaviorTemplate::PLAY_EFFECT: | ||||
| 		behavior = new PlayEffectBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_IMMUNITY: | ||||
| 	case BehaviorTemplate::IMMUNITY: | ||||
| 		behavior = new ImmunityBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_DAMAGE_BUFF: break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_DAMAGE_ABSORBTION: | ||||
| 	case BehaviorTemplate::DAMAGE_BUFF: break; | ||||
| 	case BehaviorTemplate::DAMAGE_ABSORBTION: | ||||
| 		behavior = new DamageAbsorptionBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_OVER_TIME: | ||||
| 	case BehaviorTemplate::OVER_TIME: | ||||
| 		behavior = new OverTimeBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_IMAGINATION: | ||||
| 	case BehaviorTemplate::IMAGINATION: | ||||
| 		behavior = new ImaginationBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_TARGET_CASTER: | ||||
| 	case BehaviorTemplate::TARGET_CASTER: | ||||
| 		behavior = new TargetCasterBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_STUN: | ||||
| 	case BehaviorTemplate::STUN: | ||||
| 		behavior = new StunBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_DURATION: | ||||
| 	case BehaviorTemplate::DURATION: | ||||
| 		behavior = new DurationBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_KNOCKBACK: | ||||
| 	case BehaviorTemplate::KNOCKBACK: | ||||
| 		behavior = new KnockbackBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_ATTACK_DELAY: | ||||
| 	case BehaviorTemplate::ATTACK_DELAY: | ||||
| 		behavior = new AttackDelayBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_CAR_BOOST: | ||||
| 	case BehaviorTemplate::CAR_BOOST: | ||||
| 		behavior = new CarBoostBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_FALL_SPEED: | ||||
| 	case BehaviorTemplate::FALL_SPEED: | ||||
| 		behavior = new FallSpeedBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_SHIELD: break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_REPAIR_ARMOR: | ||||
| 	case BehaviorTemplate::SHIELD: break; | ||||
| 	case BehaviorTemplate::REPAIR_ARMOR: | ||||
| 		behavior = new RepairBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_SPEED: | ||||
| 	case BehaviorTemplate::SPEED: | ||||
| 		behavior = new SpeedBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_DARK_INSPIRATION: | ||||
| 	case BehaviorTemplate::DARK_INSPIRATION: | ||||
| 		behavior = new DarkInspirationBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_LOOT_BUFF: | ||||
| 	case BehaviorTemplate::LOOT_BUFF: | ||||
| 		behavior = new LootBuffBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_VENTURE_VISION: | ||||
| 	case BehaviorTemplate::VENTURE_VISION: | ||||
| 		behavior = new VentureVisionBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_SPAWN_OBJECT: | ||||
| 	case BehaviorTemplate::SPAWN_OBJECT: | ||||
| 		behavior = new SpawnBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_LAY_BRICK: break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_SWITCH: | ||||
| 	case BehaviorTemplate::LAY_BRICK: break; | ||||
| 	case BehaviorTemplate::SWITCH: | ||||
| 		behavior = new SwitchBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_BUFF: | ||||
| 	case BehaviorTemplate::BUFF: | ||||
| 		behavior = new BuffBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_JETPACK: | ||||
| 	case BehaviorTemplate::JETPACK: | ||||
| 		behavior = new JetPackBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_SKILL_EVENT: | ||||
| 	case BehaviorTemplate::SKILL_EVENT: | ||||
| 		behavior = new SkillEventBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_CONSUME_ITEM: | ||||
| 	case BehaviorTemplate::CONSUME_ITEM: | ||||
| 		behavior = new ConsumeItemBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_SKILL_CAST_FAILED: | ||||
| 	case BehaviorTemplate::SKILL_CAST_FAILED: | ||||
| 		behavior = new SkillCastFailedBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_IMITATION_SKUNK_STINK: break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_CHANGE_IDLE_FLAGS: | ||||
| 	case BehaviorTemplate::IMITATION_SKUNK_STINK: break; | ||||
| 	case BehaviorTemplate::CHANGE_IDLE_FLAGS: | ||||
| 		behavior = new ChangeIdleFlagsBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_APPLY_BUFF: | ||||
| 	case BehaviorTemplate::APPLY_BUFF: | ||||
| 		behavior = new ApplyBuffBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_CHAIN: | ||||
| 	case BehaviorTemplate::CHAIN: | ||||
| 		behavior = new ChainBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_CHANGE_ORIENTATION: | ||||
| 	case BehaviorTemplate::CHANGE_ORIENTATION: | ||||
| 		behavior = new ChangeOrientationBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_FORCE_MOVEMENT: | ||||
| 	case BehaviorTemplate::FORCE_MOVEMENT: | ||||
| 		behavior = new ForceMovementBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_INTERRUPT: | ||||
| 	case BehaviorTemplate::INTERRUPT: | ||||
| 		behavior = new InterruptBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_ALTER_COOLDOWN: break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_CHARGE_UP: | ||||
| 	case BehaviorTemplate::ALTER_COOLDOWN: break; | ||||
| 	case BehaviorTemplate::CHARGE_UP: | ||||
| 		behavior = new ChargeUpBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_SWITCH_MULTIPLE: | ||||
| 	case BehaviorTemplate::SWITCH_MULTIPLE: | ||||
| 		behavior = new SwitchMultipleBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_START: | ||||
| 	case BehaviorTemplate::START: | ||||
| 		behavior = new StartBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_END: | ||||
| 	case BehaviorTemplate::END: | ||||
| 		behavior = new EndBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_ALTER_CHAIN_DELAY: break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_CAMERA: break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_REMOVE_BUFF: | ||||
| 	case BehaviorTemplate::ALTER_CHAIN_DELAY: break; | ||||
| 	case BehaviorTemplate::CAMERA: break; | ||||
| 	case BehaviorTemplate::REMOVE_BUFF: | ||||
| 		behavior = new RemoveBuffBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_GRAB: break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_MODULAR_BUILD: break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_NPC_COMBAT_SKILL: | ||||
| 	case BehaviorTemplate::GRAB: break; | ||||
| 	case BehaviorTemplate::MODULAR_BUILD: break; | ||||
| 	case BehaviorTemplate::NPC_COMBAT_SKILL: | ||||
| 		behavior = new NpcCombatSkillBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_BLOCK: | ||||
| 	case BehaviorTemplate::BLOCK: | ||||
| 		behavior = new BlockBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_VERIFY: | ||||
| 	case BehaviorTemplate::VERIFY: | ||||
| 		behavior = new VerifyBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_TAUNT: | ||||
| 	case BehaviorTemplate::TAUNT: | ||||
| 		behavior = new TauntBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_AIR_MOVEMENT: | ||||
| 	case BehaviorTemplate::AIR_MOVEMENT: | ||||
| 		behavior = new AirMovementBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_SPAWN_QUICKBUILD: | ||||
| 	case BehaviorTemplate::SPAWN_QUICKBUILD: | ||||
| 		behavior = new SpawnBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_PULL_TO_POINT: | ||||
| 	case BehaviorTemplate::PULL_TO_POINT: | ||||
| 		behavior = new PullToPointBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_PROPERTY_ROTATE: break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_DAMAGE_REDUCTION: | ||||
| 	case BehaviorTemplate::PROPERTY_ROTATE: break; | ||||
| 	case BehaviorTemplate::DAMAGE_REDUCTION: | ||||
| 		behavior = new DamageReductionBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_PROPERTY_TELEPORT: | ||||
| 	case BehaviorTemplate::PROPERTY_TELEPORT: | ||||
| 		behavior = new PropertyTeleportBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_PROPERTY_CLEAR_TARGET: | ||||
| 	case BehaviorTemplate::PROPERTY_CLEAR_TARGET: | ||||
| 		behavior = new ClearTargetBehavior(behaviorId); | ||||
| 		break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_TAKE_PICTURE: break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_MOUNT: break; | ||||
| 	case BehaviorTemplates::BEHAVIOR_SKILL_SET: break; | ||||
| 	case BehaviorTemplate::TAKE_PICTURE: break; | ||||
| 	case BehaviorTemplate::MOUNT: break; | ||||
| 	case BehaviorTemplate::SKILL_SET: break; | ||||
| 	default: | ||||
| 		//LOG("Failed to load behavior with invalid template id (%i)!", templateId); | ||||
| 		break; | ||||
| @@ -296,19 +296,19 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) { | ||||
| 	return behavior; | ||||
| } | ||||
|  | ||||
| BehaviorTemplates Behavior::GetBehaviorTemplate(const uint32_t behaviorId) { | ||||
| BehaviorTemplate Behavior::GetBehaviorTemplate(const uint32_t behaviorId) { | ||||
| 	auto behaviorTemplateTable = CDClientManager::GetTable<CDBehaviorTemplateTable>(); | ||||
|  | ||||
| 	BehaviorTemplates templateID = BehaviorTemplates::BEHAVIOR_EMPTY; | ||||
| 	BehaviorTemplate templateID = BehaviorTemplate::EMPTY; | ||||
| 	// Find behavior template by its behavior id.  Default to 0. | ||||
| 	if (behaviorTemplateTable) { | ||||
| 		auto templateEntry = behaviorTemplateTable->GetByBehaviorID(behaviorId); | ||||
| 		if (templateEntry.behaviorID == behaviorId) { | ||||
| 			templateID = static_cast<BehaviorTemplates>(templateEntry.templateID); | ||||
| 			templateID = static_cast<BehaviorTemplate>(templateEntry.templateID); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (templateID == BehaviorTemplates::BEHAVIOR_EMPTY && behaviorId != 0) { | ||||
| 	if (templateID == BehaviorTemplate::EMPTY && behaviorId != 0) { | ||||
| 		LOG("Failed to load behavior template with id (%i)!", behaviorId); | ||||
| 	} | ||||
|  | ||||
| @@ -335,26 +335,22 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID | ||||
|  | ||||
| 	const auto typeString = GeneralUtils::UTF16ToWTF8(type); | ||||
|  | ||||
| 	if (m_effectNames == nullptr) { | ||||
| 		m_effectNames = new std::unordered_map<std::string, std::string>(); | ||||
| 	} else { | ||||
| 		const auto pair = m_effectNames->find(typeString); | ||||
| 	const auto itr = m_effectNames.find(typeString); | ||||
|  | ||||
| 		if (type.empty()) { | ||||
| 			type = GeneralUtils::ASCIIToUTF16(*m_effectType); | ||||
| 		} | ||||
| 	if (type.empty()) { | ||||
| 		type = GeneralUtils::ASCIIToUTF16(m_effectType); | ||||
| 	} | ||||
|  | ||||
| 		if (pair != m_effectNames->end()) { | ||||
| 			if (renderComponent == nullptr) { | ||||
| 				GameMessages::SendPlayFXEffect(targetEntity, effectId, type, pair->second, secondary, 1, 1, true); | ||||
|  | ||||
| 				return; | ||||
| 			} | ||||
|  | ||||
| 			renderComponent->PlayEffect(effectId, type, pair->second, secondary); | ||||
| 	if (itr != m_effectNames.end()) { | ||||
| 		if (renderComponent == nullptr) { | ||||
| 			GameMessages::SendPlayFXEffect(targetEntity, effectId, type, itr->second, secondary, 1, 1, true); | ||||
|  | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		renderComponent->PlayEffect(effectId, type, itr->second, secondary); | ||||
|  | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	// The SQlite result object becomes invalid if the query object leaves scope. | ||||
| @@ -388,12 +384,12 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID | ||||
|  | ||||
| 		type = GeneralUtils::ASCIIToUTF16(typeResult); | ||||
|  | ||||
| 		m_effectType = new std::string(typeResult); | ||||
| 		m_effectType = typeResult; | ||||
| 	} | ||||
|  | ||||
| 	result.finalize(); | ||||
|  | ||||
| 	m_effectNames->insert_or_assign(typeString, name); | ||||
| 	m_effectNames.insert_or_assign(typeString, name); | ||||
|  | ||||
| 	if (renderComponent == nullptr) { | ||||
| 		GameMessages::SendPlayFXEffect(targetEntity, effectId, type, name, secondary, 1, 1, true); | ||||
| @@ -423,8 +419,7 @@ Behavior::Behavior(const uint32_t behaviorId) { | ||||
|  | ||||
| 	if (behaviorId == 0) { | ||||
| 		this->m_effectId = 0; | ||||
| 		this->m_effectHandle = nullptr; | ||||
| 		this->m_templateId = BehaviorTemplates::BEHAVIOR_EMPTY; | ||||
| 		this->m_templateId = BehaviorTemplate::EMPTY; | ||||
| 	} | ||||
|  | ||||
| 	// Make sure we do not proceed if we are trying to load an invalid behavior | ||||
| @@ -432,17 +427,16 @@ Behavior::Behavior(const uint32_t behaviorId) { | ||||
| 		LOG("Failed to load behavior with id (%i)!", behaviorId); | ||||
|  | ||||
| 		this->m_effectId = 0; | ||||
| 		this->m_effectHandle = nullptr; | ||||
| 		this->m_templateId = BehaviorTemplates::BEHAVIOR_EMPTY; | ||||
| 		this->m_templateId = BehaviorTemplate::EMPTY; | ||||
|  | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	this->m_templateId = static_cast<BehaviorTemplates>(templateInDatabase.templateID); | ||||
| 	this->m_templateId = static_cast<BehaviorTemplate>(templateInDatabase.templateID); | ||||
|  | ||||
| 	this->m_effectId = templateInDatabase.effectID; | ||||
|  | ||||
| 	this->m_effectHandle = *templateInDatabase.effectHandle != "" ? new std::string(*templateInDatabase.effectHandle) : nullptr; | ||||
| 	this->m_effectHandle = *templateInDatabase.effectHandle; | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -507,9 +501,3 @@ void Behavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, | ||||
|  | ||||
| void Behavior::SyncCalculation(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) { | ||||
| } | ||||
|  | ||||
| Behavior::~Behavior() { | ||||
| 	delete m_effectNames; | ||||
| 	delete m_effectType; | ||||
| 	delete m_effectHandle; | ||||
| } | ||||
|   | ||||
| @@ -6,7 +6,7 @@ | ||||
| #include <unordered_map> | ||||
|  | ||||
| #include "BitStream.h" | ||||
| #include "BehaviorTemplates.h" | ||||
| #include "BehaviorTemplate.h" | ||||
| #include "dCommonVars.h" | ||||
|  | ||||
| struct BehaviorContext; | ||||
| @@ -26,7 +26,7 @@ public: | ||||
|  | ||||
| 	static Behavior* CreateBehavior(uint32_t behaviorId); | ||||
|  | ||||
| 	static BehaviorTemplates GetBehaviorTemplate(uint32_t behaviorId); | ||||
| 	static BehaviorTemplate GetBehaviorTemplate(uint32_t behaviorId); | ||||
|  | ||||
| 	/* | ||||
| 	 * Utilities | ||||
| @@ -39,11 +39,11 @@ public: | ||||
| 	 */ | ||||
|  | ||||
| 	uint32_t m_behaviorId; | ||||
| 	BehaviorTemplates m_templateId; | ||||
| 	BehaviorTemplate m_templateId; | ||||
| 	uint32_t m_effectId; | ||||
| 	std::string* m_effectHandle = nullptr; | ||||
| 	std::unordered_map<std::string, std::string>* m_effectNames = nullptr; | ||||
| 	std::string* m_effectType = nullptr; | ||||
| 	std::string m_effectHandle; | ||||
| 	std::unordered_map<std::string, std::string> m_effectNames; | ||||
| 	std::string m_effectType; | ||||
|  | ||||
| 	/* | ||||
| 	 * Behavior parameters | ||||
| @@ -88,5 +88,11 @@ public: | ||||
| 	 */ | ||||
|  | ||||
| 	explicit Behavior(uint32_t behaviorId); | ||||
| 	virtual ~Behavior(); | ||||
| 	virtual ~Behavior() = default; | ||||
|  | ||||
| 	Behavior(const Behavior& other) = default; | ||||
| 	Behavior(Behavior&& other) = default; | ||||
|  | ||||
| 	Behavior& operator=(const Behavior& other) = default; | ||||
| 	Behavior& operator=(Behavior&& other) = default; | ||||
| }; | ||||
|   | ||||
							
								
								
									
										70
									
								
								dGame/dBehaviors/BehaviorTemplate.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								dGame/dBehaviors/BehaviorTemplate.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | ||||
| #pragma once | ||||
|  | ||||
| enum class BehaviorTemplate : unsigned int { | ||||
| 	EMPTY, // Not a real behavior, indicates invalid behaviors | ||||
| 	BASIC_ATTACK, | ||||
| 	TAC_ARC, | ||||
| 	AND, | ||||
| 	PROJECTILE_ATTACK, | ||||
| 	HEAL, | ||||
| 	MOVEMENT_SWITCH, | ||||
| 	AREA_OF_EFFECT, | ||||
| 	PLAY_EFFECT, | ||||
| 	IMMUNITY, | ||||
| 	DAMAGE_BUFF, | ||||
| 	DAMAGE_ABSORBTION, | ||||
| 	OVER_TIME, | ||||
| 	IMAGINATION, | ||||
| 	TARGET_CASTER, | ||||
| 	STUN, | ||||
| 	DURATION, | ||||
| 	KNOCKBACK, | ||||
| 	ATTACK_DELAY, | ||||
| 	CAR_BOOST, | ||||
| 	FALL_SPEED, | ||||
| 	SHIELD, | ||||
| 	REPAIR_ARMOR, | ||||
| 	SPEED, | ||||
| 	DARK_INSPIRATION, | ||||
| 	LOOT_BUFF, | ||||
| 	VENTURE_VISION, | ||||
| 	SPAWN_OBJECT, | ||||
| 	LAY_BRICK, | ||||
| 	SWITCH, | ||||
| 	BUFF, | ||||
| 	JETPACK, | ||||
| 	SKILL_EVENT, | ||||
| 	CONSUME_ITEM, | ||||
| 	SKILL_CAST_FAILED, | ||||
| 	IMITATION_SKUNK_STINK, | ||||
| 	CHANGE_IDLE_FLAGS, | ||||
| 	APPLY_BUFF, | ||||
| 	CHAIN, | ||||
| 	CHANGE_ORIENTATION, | ||||
| 	FORCE_MOVEMENT, | ||||
| 	INTERRUPT, | ||||
| 	ALTER_COOLDOWN, | ||||
| 	CHARGE_UP, | ||||
| 	SWITCH_MULTIPLE, | ||||
| 	START, | ||||
| 	END, | ||||
| 	ALTER_CHAIN_DELAY, | ||||
| 	CAMERA, | ||||
| 	REMOVE_BUFF, | ||||
| 	GRAB, | ||||
| 	MODULAR_BUILD, | ||||
| 	NPC_COMBAT_SKILL, | ||||
| 	BLOCK, | ||||
| 	VERIFY, | ||||
| 	TAUNT, | ||||
| 	AIR_MOVEMENT, | ||||
| 	SPAWN_QUICKBUILD, | ||||
| 	PULL_TO_POINT, | ||||
| 	PROPERTY_ROTATE, | ||||
| 	DAMAGE_REDUCTION, | ||||
| 	PROPERTY_TELEPORT, | ||||
| 	PROPERTY_CLEAR_TARGET, | ||||
| 	TAKE_PICTURE, | ||||
| 	MOUNT, | ||||
| 	SKILL_SET | ||||
| }; | ||||
| @@ -1 +0,0 @@ | ||||
| #include "BehaviorTemplates.h" | ||||
| @@ -1,70 +0,0 @@ | ||||
| #pragma once | ||||
|  | ||||
| enum class BehaviorTemplates : unsigned int { | ||||
| 	BEHAVIOR_EMPTY, // Not a real behavior, indicates invalid behaviors | ||||
| 	BEHAVIOR_BASIC_ATTACK, | ||||
| 	BEHAVIOR_TAC_ARC, | ||||
| 	BEHAVIOR_AND, | ||||
| 	BEHAVIOR_PROJECTILE_ATTACK, | ||||
| 	BEHAVIOR_HEAL, | ||||
| 	BEHAVIOR_MOVEMENT_SWITCH, | ||||
| 	BEHAVIOR_AREA_OF_EFFECT, | ||||
| 	BEHAVIOR_PLAY_EFFECT, | ||||
| 	BEHAVIOR_IMMUNITY, | ||||
| 	BEHAVIOR_DAMAGE_BUFF, | ||||
| 	BEHAVIOR_DAMAGE_ABSORBTION, | ||||
| 	BEHAVIOR_OVER_TIME, | ||||
| 	BEHAVIOR_IMAGINATION, | ||||
| 	BEHAVIOR_TARGET_CASTER, | ||||
| 	BEHAVIOR_STUN, | ||||
| 	BEHAVIOR_DURATION, | ||||
| 	BEHAVIOR_KNOCKBACK, | ||||
| 	BEHAVIOR_ATTACK_DELAY, | ||||
| 	BEHAVIOR_CAR_BOOST, | ||||
| 	BEHAVIOR_FALL_SPEED, | ||||
| 	BEHAVIOR_SHIELD, | ||||
| 	BEHAVIOR_REPAIR_ARMOR, | ||||
| 	BEHAVIOR_SPEED, | ||||
| 	BEHAVIOR_DARK_INSPIRATION, | ||||
| 	BEHAVIOR_LOOT_BUFF, | ||||
| 	BEHAVIOR_VENTURE_VISION, | ||||
| 	BEHAVIOR_SPAWN_OBJECT, | ||||
| 	BEHAVIOR_LAY_BRICK, | ||||
| 	BEHAVIOR_SWITCH, | ||||
| 	BEHAVIOR_BUFF, | ||||
| 	BEHAVIOR_JETPACK, | ||||
| 	BEHAVIOR_SKILL_EVENT, | ||||
| 	BEHAVIOR_CONSUME_ITEM, | ||||
| 	BEHAVIOR_SKILL_CAST_FAILED, | ||||
| 	BEHAVIOR_IMITATION_SKUNK_STINK, | ||||
| 	BEHAVIOR_CHANGE_IDLE_FLAGS, | ||||
| 	BEHAVIOR_APPLY_BUFF, | ||||
| 	BEHAVIOR_CHAIN, | ||||
| 	BEHAVIOR_CHANGE_ORIENTATION, | ||||
| 	BEHAVIOR_FORCE_MOVEMENT, | ||||
| 	BEHAVIOR_INTERRUPT, | ||||
| 	BEHAVIOR_ALTER_COOLDOWN, | ||||
| 	BEHAVIOR_CHARGE_UP, | ||||
| 	BEHAVIOR_SWITCH_MULTIPLE, | ||||
| 	BEHAVIOR_START, | ||||
| 	BEHAVIOR_END, | ||||
| 	BEHAVIOR_ALTER_CHAIN_DELAY, | ||||
| 	BEHAVIOR_CAMERA, | ||||
| 	BEHAVIOR_REMOVE_BUFF, | ||||
| 	BEHAVIOR_GRAB, | ||||
| 	BEHAVIOR_MODULAR_BUILD, | ||||
| 	BEHAVIOR_NPC_COMBAT_SKILL, | ||||
| 	BEHAVIOR_BLOCK, | ||||
| 	BEHAVIOR_VERIFY, | ||||
| 	BEHAVIOR_TAUNT, | ||||
| 	BEHAVIOR_AIR_MOVEMENT, | ||||
| 	BEHAVIOR_SPAWN_QUICKBUILD, | ||||
| 	BEHAVIOR_PULL_TO_POINT, | ||||
| 	BEHAVIOR_PROPERTY_ROTATE, | ||||
| 	BEHAVIOR_DAMAGE_REDUCTION, | ||||
| 	BEHAVIOR_PROPERTY_TELEPORT, | ||||
| 	BEHAVIOR_PROPERTY_CLEAR_TARGET, | ||||
| 	BEHAVIOR_TAKE_PICTURE, | ||||
| 	BEHAVIOR_MOUNT, | ||||
| 	BEHAVIOR_SKILL_SET | ||||
| }; | ||||
| @@ -7,7 +7,6 @@ set(DGAME_DBEHAVIORS_SOURCES "AirMovementBehavior.cpp" | ||||
| 	"Behavior.cpp" | ||||
| 	"BehaviorBranchContext.cpp" | ||||
| 	"BehaviorContext.cpp" | ||||
| 	"BehaviorTemplates.cpp" | ||||
| 	"BlockBehavior.cpp" | ||||
| 	"BuffBehavior.cpp" | ||||
| 	"CarBoostBehavior.cpp" | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
| #include "Logger.h" | ||||
|  | ||||
| void ForceMovementBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, const BehaviorBranchContext branch) { | ||||
| 	if (this->m_hitAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && this->m_hitEnemyAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && this->m_hitFactionAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY) { | ||||
| 	if (this->m_hitAction->m_templateId == BehaviorTemplate::EMPTY && this->m_hitEnemyAction->m_templateId == BehaviorTemplate::EMPTY && this->m_hitFactionAction->m_templateId == BehaviorTemplate::EMPTY) { | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| @@ -38,7 +38,7 @@ void ForceMovementBehavior::Sync(BehaviorContext* context, RakNet::BitStream& bi | ||||
| } | ||||
|  | ||||
| void ForceMovementBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) { | ||||
| 	if (this->m_hitAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && this->m_hitEnemyAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && this->m_hitFactionAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY) { | ||||
| 	if (this->m_hitAction->m_templateId == BehaviorTemplate::EMPTY && this->m_hitEnemyAction->m_templateId == BehaviorTemplate::EMPTY && this->m_hitFactionAction->m_templateId == BehaviorTemplate::EMPTY) { | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -8,36 +8,50 @@ | ||||
|  | ||||
|  | ||||
| void InterruptBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) { | ||||
| 	if (branch.target != context->originator) { | ||||
| 		bool unknown = false; | ||||
| 	LWOOBJID usedTarget = m_target ? branch.target : context->originator; | ||||
|  | ||||
| 		if (!bitStream.Read(unknown)) { | ||||
| 			LOG("Unable to read unknown1 from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits()); | ||||
| 	if (usedTarget != context->originator) { | ||||
| 		bool isTargetImmuneStuns = false; | ||||
| 		if (!bitStream.Read(isTargetImmuneStuns)) { | ||||
| 			LOG("Unable to read isTargetImmune from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits()); | ||||
| 			return; | ||||
| 		}; | ||||
|  | ||||
| 		if (unknown) return; | ||||
| 		if (isTargetImmuneStuns) return; | ||||
| 	} | ||||
|  | ||||
| 	if (!this->m_interruptBlock) { | ||||
| 		bool unknown = false; | ||||
|  | ||||
| 		if (!bitStream.Read(unknown)) { | ||||
| 			LOG("Unable to read unknown2 from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits()); | ||||
| 		bool isBlockingInterrupts = false; | ||||
| 		if (!bitStream.Read(isBlockingInterrupts)) { | ||||
| 			LOG("Unable to read isBlockingInterrupts from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits()); | ||||
| 			return; | ||||
| 		}; | ||||
|  | ||||
| 		if (unknown) return; | ||||
| 		if (isBlockingInterrupts) return; | ||||
| 	} | ||||
|  | ||||
| 	if (this->m_target) // Guess... | ||||
| 	{ | ||||
| 		bool unknown = false; | ||||
| 	bool hasInterruptedStatusEffects = false; | ||||
| 	if (!bitStream.Read(hasInterruptedStatusEffects)) { | ||||
| 		LOG("Unable to read hasInterruptedStatusEffects from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits()); | ||||
| 		return; | ||||
| 	}; | ||||
|  | ||||
| 		if (!bitStream.Read(unknown)) { | ||||
| 			LOG("Unable to read unknown3 from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits()); | ||||
| 			return; | ||||
| 		}; | ||||
| 	if (hasInterruptedStatusEffects) { | ||||
| 		bool hasMoreInterruptedStatusEffects = false; | ||||
| 		int32_t loopLimit = 0; | ||||
| 		while (bitStream.Read(hasMoreInterruptedStatusEffects) && hasMoreInterruptedStatusEffects) { | ||||
| 			int32_t statusEffectID = 0; | ||||
| 			bitStream.Read(statusEffectID); | ||||
| 			// nothing happens with this data yes.  I have no idea why or what it was used for, but the client literally just reads it and does nothing with it. | ||||
| 			// 0x004faca4 for a reference.  it also has a hard loop limit of 100 soo, | ||||
| 			loopLimit++; | ||||
| 			if (loopLimit > 100) { | ||||
| 				// if this is hit you have a problem | ||||
| 				LOG("Loop limit reached for interrupted status effects, aborting Handle due to bad bitstream! %i", bitStream.GetNumberOfUnreadBits()); | ||||
| 				break; | ||||
| 			} | ||||
| 			LOG_DEBUG("Interrupted status effect ID: %i", statusEffectID); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (branch.target == context->originator) return; | ||||
| @@ -55,7 +69,8 @@ void InterruptBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitS | ||||
|  | ||||
|  | ||||
| void InterruptBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) { | ||||
| 	if (branch.target != context->originator) { | ||||
| 	LWOOBJID usedTarget = m_target ? branch.target : context->originator; | ||||
| 	if (usedTarget != context->originator) { | ||||
| 		bitStream.Write(false); | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -6,13 +6,13 @@ | ||||
| void MovementSwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, const BehaviorBranchContext branch) { | ||||
| 	uint32_t movementType{}; | ||||
| 	if (!bitStream.Read(movementType)) { | ||||
| 		if (this->m_groundAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && | ||||
| 			this->m_jumpAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && | ||||
| 			this->m_fallingAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && | ||||
| 			this->m_doubleJumpAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && | ||||
| 			this->m_airAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && | ||||
| 			this->m_jetpackAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && | ||||
| 			this->m_movingAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY) { | ||||
| 		if (this->m_groundAction->m_templateId == BehaviorTemplate::EMPTY && | ||||
| 			this->m_jumpAction->m_templateId == BehaviorTemplate::EMPTY && | ||||
| 			this->m_fallingAction->m_templateId == BehaviorTemplate::EMPTY && | ||||
| 			this->m_doubleJumpAction->m_templateId == BehaviorTemplate::EMPTY && | ||||
| 			this->m_airAction->m_templateId == BehaviorTemplate::EMPTY && | ||||
| 			this->m_jetpackAction->m_templateId == BehaviorTemplate::EMPTY && | ||||
| 			this->m_movingAction->m_templateId == BehaviorTemplate::EMPTY) { | ||||
| 			return; | ||||
| 		} | ||||
| 		LOG("Unable to read movementType from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits()); | ||||
| @@ -47,7 +47,7 @@ void MovementSwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream& | ||||
| Behavior* MovementSwitchBehavior::LoadMovementType(std::string movementType) { | ||||
| 	float actionValue = GetFloat(movementType, -1.0f); | ||||
| 	auto loadedBehavior = GetAction(actionValue != -1.0f ? actionValue : 0.0f); | ||||
| 	if (actionValue == -1.0f && loadedBehavior->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY) { | ||||
| 	if (actionValue == -1.0f && loadedBehavior->m_templateId == BehaviorTemplate::EMPTY) { | ||||
| 		loadedBehavior = this->m_groundAction; | ||||
| 	} | ||||
| 	return loadedBehavior; | ||||
|   | ||||
| @@ -9,17 +9,16 @@ void SkillEventBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bit | ||||
| 	auto* target = Game::entityManager->GetEntity(branch.target); | ||||
| 	auto* caster = Game::entityManager->GetEntity(context->originator); | ||||
|  | ||||
| 	if (caster != nullptr && target != nullptr && this->m_effectHandle != nullptr && !this->m_effectHandle->empty()) { | ||||
| 		target->GetScript()->OnSkillEventFired(target, caster, *this->m_effectHandle); | ||||
| 	if (caster != nullptr && target != nullptr && !this->m_effectHandle.empty()) { | ||||
| 		target->GetScript()->OnSkillEventFired(target, caster, this->m_effectHandle); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void | ||||
| SkillEventBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) { | ||||
| void SkillEventBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) { | ||||
| 	auto* target = Game::entityManager->GetEntity(branch.target); | ||||
| 	auto* caster = Game::entityManager->GetEntity(context->originator); | ||||
|  | ||||
| 	if (caster != nullptr && target != nullptr && this->m_effectHandle != nullptr && !this->m_effectHandle->empty()) { | ||||
| 		target->GetScript()->OnSkillEventFired(target, caster, *this->m_effectHandle); | ||||
| 	if (caster != nullptr && target != nullptr && !this->m_effectHandle.empty()) { | ||||
| 		target->GetScript()->OnSkillEventFired(target, caster, this->m_effectHandle); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -7,9 +7,9 @@ | ||||
| #include "BuffComponent.h" | ||||
|  | ||||
| void SwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, const BehaviorBranchContext branch) { | ||||
| 	auto state = true; | ||||
| 	bool state = true; | ||||
|  | ||||
| 	if (this->m_imagination > 0 || !this->m_isEnemyFaction) { | ||||
| 	if (m_imagination > 0 || m_targetHasBuff > 0 || m_Distance > -1.0f) { | ||||
| 		if (!bitStream.Read(state)) { | ||||
| 			LOG("Unable to read state from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits()); | ||||
| 			return; | ||||
| @@ -18,49 +18,59 @@ void SwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStre | ||||
|  | ||||
| 	auto* entity = Game::entityManager->GetEntity(context->originator); | ||||
|  | ||||
| 	if (entity == nullptr) { | ||||
| 		return; | ||||
| 	} | ||||
| 	if (!entity) return; | ||||
|  | ||||
| 	auto* destroyableComponent = entity->GetComponent<DestroyableComponent>(); | ||||
|  | ||||
| 	if (destroyableComponent == nullptr) { | ||||
| 		return; | ||||
| 	if (destroyableComponent) { | ||||
| 		if (m_isEnemyFaction) { | ||||
| 			auto* target = Game::entityManager->GetEntity(branch.target); | ||||
| 			if (target) state = destroyableComponent->IsEnemy(target); | ||||
| 		} | ||||
|  | ||||
| 		LOG_DEBUG("[%i] State: (%d), imagination: (%i) / (%f)", entity->GetLOT(), state, destroyableComponent->GetImagination(), destroyableComponent->GetMaxImagination()); | ||||
| 	} | ||||
|  | ||||
| 	LOG_DEBUG("[%i] State: (%d), imagination: (%i) / (%f)", entity->GetLOT(), state, destroyableComponent->GetImagination(), destroyableComponent->GetMaxImagination()); | ||||
|  | ||||
| 	if (state) { | ||||
| 		this->m_actionTrue->Handle(context, bitStream, branch); | ||||
| 	} else { | ||||
| 		this->m_actionFalse->Handle(context, bitStream, branch); | ||||
| 	} | ||||
| 	auto* behaviorToCall = state ? m_actionTrue : m_actionFalse; | ||||
| 	behaviorToCall->Handle(context, bitStream, branch); | ||||
| } | ||||
|  | ||||
| void SwitchBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) { | ||||
| 	auto state = true; | ||||
|  | ||||
| 	if (this->m_imagination > 0 || !this->m_isEnemyFaction) { | ||||
| 	bool state = true; | ||||
| 	if (m_imagination > 0 || m_targetHasBuff > 0 || m_Distance > -1.0f) { | ||||
| 		auto* entity = Game::entityManager->GetEntity(branch.target); | ||||
|  | ||||
| 		state = entity != nullptr; | ||||
|  | ||||
| 		if (state && m_targetHasBuff != 0) { | ||||
| 			auto* buffComponent = entity->GetComponent<BuffComponent>(); | ||||
| 		if (state) { | ||||
| 			if (m_targetHasBuff != 0) { | ||||
| 				auto* buffComponent = entity->GetComponent<BuffComponent>(); | ||||
|  | ||||
| 			if (buffComponent != nullptr && !buffComponent->HasBuff(m_targetHasBuff)) { | ||||
| 				state = false; | ||||
| 				if (buffComponent != nullptr && !buffComponent->HasBuff(m_targetHasBuff)) { | ||||
| 					state = false; | ||||
| 				} | ||||
| 			} else if (m_imagination > 0) { | ||||
| 				auto* destroyableComponent = entity->GetComponent<DestroyableComponent>(); | ||||
|  | ||||
| 				if (destroyableComponent && destroyableComponent->GetImagination() < m_imagination) { | ||||
| 					state = false; | ||||
| 				} | ||||
| 			} else if (m_Distance > -1.0f) { | ||||
| 				auto* originator = Game::entityManager->GetEntity(context->originator); | ||||
|  | ||||
| 				if (originator) { | ||||
| 					const auto distance = (originator->GetPosition() - entity->GetPosition()).Length(); | ||||
|  | ||||
| 					state = distance <= m_Distance; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		bitStream.Write(state); | ||||
| 	} | ||||
|  | ||||
| 	if (state) { | ||||
| 		this->m_actionTrue->Calculate(context, bitStream, branch); | ||||
| 	} else { | ||||
| 		this->m_actionFalse->Calculate(context, bitStream, branch); | ||||
| 	} | ||||
| 	auto* behaviorToCall = state ? m_actionTrue : m_actionFalse; | ||||
| 	behaviorToCall->Calculate(context, bitStream, branch); | ||||
| } | ||||
|  | ||||
| void SwitchBehavior::Load() { | ||||
| @@ -72,5 +82,7 @@ void SwitchBehavior::Load() { | ||||
|  | ||||
| 	this->m_isEnemyFaction = GetBoolean("isEnemyFaction"); | ||||
|  | ||||
| 	this->m_targetHasBuff = GetInt("target_has_buff"); | ||||
| 	this->m_targetHasBuff = GetInt("target_has_buff", -1); | ||||
|  | ||||
| 	this->m_Distance = GetFloat("distance", -1.0f); | ||||
| } | ||||
|   | ||||
| @@ -14,6 +14,8 @@ public: | ||||
|  | ||||
| 	int32_t m_targetHasBuff; | ||||
|  | ||||
| 	float m_Distance; | ||||
|  | ||||
| 	/* | ||||
| 	 * Inherited | ||||
| 	 */ | ||||
|   | ||||
| @@ -162,7 +162,6 @@ void BaseCombatAIComponent::Update(const float deltaTime) { | ||||
| 	// Check if we should stop the tether effect | ||||
| 	if (m_TetherEffectActive) { | ||||
| 		m_TetherTime -= deltaTime; | ||||
| 		const auto& info = m_MovementAI->GetInfo(); | ||||
| 		if (m_Target != LWOOBJID_EMPTY || (NiPoint3::DistanceSquared( | ||||
| 			m_StartPosition, | ||||
| 			m_Parent->GetPosition()) < 20 * 20 && m_TetherTime <= 0) | ||||
|   | ||||
| @@ -50,9 +50,44 @@ MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) : | ||||
| 	m_CurrentSpeed = 0; | ||||
| 	m_MaxSpeed = 0; | ||||
| 	m_LockRotation = false; | ||||
| 	m_Path = nullptr; | ||||
| 	m_SourcePosition = m_Parent->GetPosition(); | ||||
| 	m_Paused = false; | ||||
| 	m_SavedVelocity = NiPoint3Constant::ZERO; | ||||
|  | ||||
| 	if (!m_Parent->GetComponent<BaseCombatAIComponent>()) SetPath(m_Parent->GetVarAsString(u"attached_path")); | ||||
| } | ||||
|  | ||||
| void MovementAIComponent::SetPath(const std::string pathName) { | ||||
| 	m_Path = Game::zoneManager->GetZone()->GetPath(pathName); | ||||
| 	if (!pathName.empty()) LOG("WARNING: %s path %s", m_Path ? "Found" : "Failed to find", pathName.c_str()); | ||||
| 	if (!m_Path) return; | ||||
| 	SetMaxSpeed(1); | ||||
| 	SetCurrentSpeed(m_BaseSpeed); | ||||
| 	SetPath(m_Path->pathWaypoints); | ||||
| } | ||||
|  | ||||
| void MovementAIComponent::Pause() { | ||||
| 	if (m_Paused) return; | ||||
| 	m_Paused = true; | ||||
| 	SetPosition(ApproximateLocation()); | ||||
| 	m_SavedVelocity = GetVelocity(); | ||||
| 	SetVelocity(NiPoint3Constant::ZERO); | ||||
| 	Game::entityManager->SerializeEntity(m_Parent); | ||||
| } | ||||
|  | ||||
| void MovementAIComponent::Resume() { | ||||
| 	if (!m_Paused) return; | ||||
| 	m_Paused = false; | ||||
| 	SetVelocity(m_SavedVelocity); | ||||
| 	m_SavedVelocity = NiPoint3Constant::ZERO; | ||||
| 	SetRotation(NiQuaternion::LookAt(m_Parent->GetPosition(), m_NextWaypoint)); | ||||
| 	Game::entityManager->SerializeEntity(m_Parent); | ||||
| } | ||||
|  | ||||
| void MovementAIComponent::Update(const float deltaTime) { | ||||
| 	if (m_Paused) return; | ||||
|  | ||||
| 	if (m_PullingToPoint) { | ||||
| 		const auto source = GetCurrentWaypoint(); | ||||
|  | ||||
| @@ -81,64 +116,65 @@ void MovementAIComponent::Update(const float deltaTime) { | ||||
| 	} | ||||
|  | ||||
| 	m_TimeTravelled += deltaTime; | ||||
|  | ||||
| 	SetPosition(ApproximateLocation()); | ||||
|  | ||||
| 	if (m_TimeTravelled < m_TimeToTravel) return; | ||||
| 	m_TimeTravelled = 0.0f; | ||||
|  | ||||
| 	const auto source = GetCurrentWaypoint(); | ||||
|  | ||||
| 	SetPosition(source); | ||||
|  | ||||
| 	NiPoint3 velocity = NiPoint3Constant::ZERO; | ||||
| 	m_SourcePosition = source; | ||||
|  | ||||
| 	if (m_Acceleration > 0 && m_BaseSpeed > 0 && AdvanceWaypointIndex()) // Do we have another waypoint to seek? | ||||
| 	{ | ||||
| 		m_NextWaypoint = GetCurrentWaypoint(); | ||||
|  | ||||
| 		if (m_NextWaypoint == source) { | ||||
| 			m_TimeToTravel = 0.0f; | ||||
| 		} else { | ||||
| 			m_CurrentSpeed = std::min(m_CurrentSpeed + m_Acceleration, m_MaxSpeed); | ||||
|  | ||||
| 			goto nextAction; | ||||
| 			const auto speed = m_CurrentSpeed * m_BaseSpeed; // scale speed based on base speed | ||||
|  | ||||
| 			const auto delta = m_NextWaypoint - source; | ||||
|  | ||||
| 			// Normalize the vector | ||||
| 			const auto length = delta.Length(); | ||||
| 			if (length > 0.0f) { | ||||
| 				SetVelocity((delta / length) * speed); | ||||
| 			} | ||||
|  | ||||
| 			// Calclute the time it will take to reach the next waypoint with the current speed | ||||
| 			m_TimeTravelled = 0.0f; | ||||
| 			m_TimeToTravel = length / speed; | ||||
|  | ||||
| 			SetRotation(NiQuaternion::LookAt(source, m_NextWaypoint)); | ||||
| 		} | ||||
|  | ||||
| 		if (m_CurrentSpeed < m_MaxSpeed) { | ||||
| 			m_CurrentSpeed += m_Acceleration; | ||||
| 		} | ||||
|  | ||||
| 		if (m_CurrentSpeed > m_MaxSpeed) { | ||||
| 			m_CurrentSpeed = m_MaxSpeed; | ||||
| 		} | ||||
|  | ||||
| 		const auto speed = m_CurrentSpeed * m_BaseSpeed; // scale speed based on base speed | ||||
|  | ||||
| 		const auto delta = m_NextWaypoint - source; | ||||
|  | ||||
| 		// Normalize the vector | ||||
| 		const auto length = delta.Length(); | ||||
| 		if (length > 0) { | ||||
| 			velocity = (delta / length) * speed; | ||||
| 		} | ||||
|  | ||||
| 		// Calclute the time it will take to reach the next waypoint with the current speed | ||||
| 		m_TimeTravelled = 0.0f; | ||||
| 		m_TimeToTravel = length / speed; | ||||
|  | ||||
| 		SetRotation(NiQuaternion::LookAt(source, m_NextWaypoint)); | ||||
| 	} else { | ||||
| 		// Check if there are more waypoints in the queue, if so set our next destination to the next waypoint | ||||
| 		if (m_CurrentPath.empty()) { | ||||
| 			Stop(); | ||||
|  | ||||
| 			return; | ||||
| 			if (m_Path) { | ||||
| 				if (m_Path->pathBehavior == PathBehavior::Loop) { | ||||
| 					SetPath(m_Path->pathWaypoints); | ||||
| 				} else if (m_Path->pathBehavior == PathBehavior::Bounce) { | ||||
| 					std::vector<PathWaypoint> waypoints = m_Path->pathWaypoints; | ||||
| 					std::reverse(waypoints.begin(), waypoints.end()); | ||||
| 					SetPath(waypoints); | ||||
| 				} else if (m_Path->pathBehavior == PathBehavior::Once) { | ||||
| 					Stop(); | ||||
| 					return; | ||||
| 				} | ||||
| 			} else { | ||||
| 				Stop(); | ||||
| 				return; | ||||
| 			} | ||||
| 		} | ||||
| 		SetDestination(m_CurrentPath.top()); | ||||
| 		SetDestination(m_CurrentPath.top().position); | ||||
|  | ||||
| 		m_CurrentPath.pop(); | ||||
| 	} | ||||
|  | ||||
| nextAction: | ||||
|  | ||||
| 	SetVelocity(velocity); | ||||
|  | ||||
| 	Game::entityManager->SerializeEntity(m_Parent); | ||||
| } | ||||
|  | ||||
| @@ -161,7 +197,7 @@ NiPoint3 MovementAIComponent::GetCurrentWaypoint() const { | ||||
| } | ||||
|  | ||||
| NiPoint3 MovementAIComponent::ApproximateLocation() const { | ||||
| 	auto source = m_Parent->GetPosition(); | ||||
| 	auto source = m_SourcePosition; | ||||
|  | ||||
| 	if (AtFinalWaypoint()) return source; | ||||
|  | ||||
| @@ -227,13 +263,13 @@ void MovementAIComponent::PullToPoint(const NiPoint3& point) { | ||||
| 	m_PullPoint = point; | ||||
| } | ||||
|  | ||||
| void MovementAIComponent::SetPath(std::vector<NiPoint3> path) { | ||||
| void MovementAIComponent::SetPath(std::vector<PathWaypoint> path) { | ||||
| 	if (path.empty()) return; | ||||
| 	std::for_each(path.rbegin(), path.rend() - 1, [this](const NiPoint3& point) { | ||||
| 	std::for_each(path.rbegin(), path.rend() - 1, [this](const PathWaypoint& point) { | ||||
| 		this->m_CurrentPath.push(point); | ||||
| 		}); | ||||
|  | ||||
| 	SetDestination(path.front()); | ||||
| 	SetDestination(path.front().position); | ||||
| } | ||||
|  | ||||
| float MovementAIComponent::GetBaseSpeed(LOT lot) { | ||||
| @@ -278,6 +314,23 @@ void MovementAIComponent::SetRotation(const NiQuaternion& value) { | ||||
| 	if (!m_LockRotation) m_Parent->SetRotation(value); | ||||
| } | ||||
|  | ||||
| NiPoint3 MovementAIComponent::GetVelocity() const { | ||||
| 	auto* controllablePhysicsComponent = m_Parent->GetComponent<ControllablePhysicsComponent>(); | ||||
|  | ||||
| 	if (controllablePhysicsComponent != nullptr) { | ||||
| 		return controllablePhysicsComponent->GetVelocity(); | ||||
| 	} | ||||
|  | ||||
| 	auto* simplePhysicsComponent = m_Parent->GetComponent<SimplePhysicsComponent>(); | ||||
|  | ||||
| 	if (simplePhysicsComponent != nullptr) { | ||||
| 		return simplePhysicsComponent->GetVelocity(); | ||||
| 	} | ||||
|  | ||||
| 	return NiPoint3Constant::ZERO; | ||||
|  | ||||
| } | ||||
|  | ||||
| void MovementAIComponent::SetVelocity(const NiPoint3& value) { | ||||
| 	auto* controllablePhysicsComponent = m_Parent->GetComponent<ControllablePhysicsComponent>(); | ||||
|  | ||||
| @@ -294,7 +347,7 @@ void MovementAIComponent::SetVelocity(const NiPoint3& value) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void MovementAIComponent::SetDestination(const NiPoint3& destination) { | ||||
| void MovementAIComponent::SetDestination(const NiPoint3 destination) { | ||||
| 	if (m_PullingToPoint) return; | ||||
|  | ||||
| 	const auto location = ApproximateLocation(); | ||||
| @@ -303,6 +356,8 @@ void MovementAIComponent::SetDestination(const NiPoint3& destination) { | ||||
| 		SetPosition(location); | ||||
| 	} | ||||
|  | ||||
| 	m_SourcePosition = location; | ||||
|  | ||||
| 	std::vector<NiPoint3> computedPath; | ||||
| 	if (dpWorld::IsLoaded()) { | ||||
| 		computedPath = dpWorld::GetNavMesh()->GetPath(m_Parent->GetPosition(), destination, m_Info.wanderSpeed); | ||||
| @@ -319,8 +374,7 @@ void MovementAIComponent::SetDestination(const NiPoint3& destination) { | ||||
| 		auto step = delta / 10.0f; | ||||
|  | ||||
| 		for (int i = 0; i < 10; i++) { | ||||
| 			// TODO: Replace this with += when the NiPoint3::operator+= is fixed | ||||
| 			start = start + step; | ||||
| 			start += step; | ||||
|  | ||||
| 			computedPath.push_back(start); | ||||
| 		} | ||||
|   | ||||
| @@ -14,11 +14,14 @@ | ||||
| #include "Logger.h" | ||||
| #include "Component.h" | ||||
| #include "eReplicaComponentType.h" | ||||
| #include "Zone.h" | ||||
| #include <vector> | ||||
|  | ||||
| class ControllablePhysicsComponent; | ||||
| class BaseCombatAIComponent; | ||||
|  | ||||
| struct Path; | ||||
|  | ||||
| /** | ||||
|  * Information that describes the different variables used to make an entity move around | ||||
|  */ | ||||
| @@ -61,6 +64,8 @@ public: | ||||
|  | ||||
| 	MovementAIComponent(Entity* parentEntity, MovementAIInfo info); | ||||
|  | ||||
| 	void SetPath(const std::string pathName); | ||||
|  | ||||
| 	void Update(float deltaTime) override; | ||||
|  | ||||
| 	/** | ||||
| @@ -73,7 +78,7 @@ public: | ||||
| 	 * Set a destination point for the entity to move towards | ||||
| 	 * @param value the destination point to move towards | ||||
| 	 */ | ||||
| 	void SetDestination(const NiPoint3& value); | ||||
| 	void SetDestination(const NiPoint3 value); | ||||
|  | ||||
| 	/** | ||||
| 	 * Returns the current rotation this entity is moving towards | ||||
| @@ -189,7 +194,13 @@ public: | ||||
| 	 * Sets a path to follow for the AI | ||||
| 	 * @param path the path to follow | ||||
| 	 */ | ||||
| 	void SetPath(std::vector<NiPoint3> path); | ||||
| 	void SetPath(std::vector<PathWaypoint> path); | ||||
|  | ||||
| 	void Pause(); | ||||
|  | ||||
| 	void Resume(); | ||||
|  | ||||
| 	NiPoint3 GetVelocity() const; | ||||
|  | ||||
| 	/** | ||||
| 	 * Returns the base speed from the DB for a given LOT | ||||
| @@ -301,7 +312,15 @@ private: | ||||
| 	/** | ||||
| 	 * The path from the current position to the destination. | ||||
| 	 */ | ||||
| 	std::stack<NiPoint3> m_CurrentPath; | ||||
| 	std::stack<PathWaypoint> m_CurrentPath; | ||||
|  | ||||
| 	const Path* m_Path = nullptr; | ||||
|  | ||||
| 	NiPoint3 m_SourcePosition; | ||||
|  | ||||
| 	bool m_Paused; | ||||
|  | ||||
| 	NiPoint3 m_SavedVelocity; | ||||
| }; | ||||
|  | ||||
| #endif // MOVEMENTAICOMPONENT_H | ||||
|   | ||||
| @@ -64,6 +64,7 @@ void ProximityMonitorComponent::Update(float deltaTime) { | ||||
| 	for (const auto& prox : m_ProximitiesData) { | ||||
| 		if (!prox.second) continue; | ||||
|  | ||||
| 		prox.second->SetPosition(m_Parent->GetPosition()); | ||||
| 		//Process enter events | ||||
| 		for (auto* en : prox.second->GetNewObjects()) { | ||||
| 			m_Parent->OnCollisionProximity(en->GetObjectID(), prox.first, "ENTER"); | ||||
|   | ||||
| @@ -1,11 +1,11 @@ | ||||
| #include "WanderingVendor.h" | ||||
| #include "MovementAIComponent.h" | ||||
| #include "ProximityMonitorComponent.h" | ||||
| #include <ranges> | ||||
|  | ||||
| void WanderingVendor::OnStartup(Entity* self) { | ||||
| 	auto movementAIComponent = self->GetComponent<MovementAIComponent>(); | ||||
| 	if (!movementAIComponent) return; | ||||
| 	// movementAIComponent->Resume(); | ||||
| 	self->SetProximityRadius(10, "playermonitor"); | ||||
| } | ||||
|  | ||||
| @@ -13,14 +13,23 @@ void WanderingVendor::OnProximityUpdate(Entity* self, Entity* entering, std::str | ||||
| 	if (status == "ENTER" && entering->IsPlayer()) { | ||||
| 		auto movementAIComponent = self->GetComponent<MovementAIComponent>(); | ||||
| 		if (!movementAIComponent) return; | ||||
| 		// movementAIComponent->Pause(); | ||||
| 		movementAIComponent->Pause(); | ||||
| 		self->CancelTimer("startWalking"); | ||||
| 	} else if (status == "LEAVE") { | ||||
| 		auto* proximityMonitorComponent = self->GetComponent<ProximityMonitorComponent>(); | ||||
| 		if (!proximityMonitorComponent) self->AddComponent<ProximityMonitorComponent>(); | ||||
|  | ||||
| 		const auto proxObjs = proximityMonitorComponent->GetProximityObjects("playermonitor"); | ||||
| 		if (proxObjs.empty()) self->AddTimer("startWalking", 1.5); | ||||
| 		bool foundPlayer = false; | ||||
| 		for (const auto id : proxObjs | std::views::keys) { | ||||
| 			auto* entity = Game::entityManager->GetEntity(id); | ||||
| 			if (entity && entity->IsPlayer()) { | ||||
| 				foundPlayer = true; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if (!foundPlayer) self->AddTimer("startWalking", 1.5); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -28,6 +37,6 @@ void WanderingVendor::OnTimerDone(Entity* self, std::string timerName) { | ||||
| 	if (timerName == "startWalking") { | ||||
| 		auto movementAIComponent = self->GetComponent<MovementAIComponent>(); | ||||
| 		if (!movementAIComponent) return; | ||||
| 		// movementAIComponent->Resume(); | ||||
| 		movementAIComponent->Resume(); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -307,11 +307,7 @@ void SGCannon::DoSpawnTimerFunc(Entity* self, const std::string& name) { | ||||
| 		movementAI->SetCurrentSpeed(toSpawn.initialSpeed); | ||||
| 		movementAI->SetHaltDistance(0.0f); | ||||
|  | ||||
| 		std::vector<NiPoint3> pathWaypoints; | ||||
|  | ||||
| 		for (const auto& waypoint : path->pathWaypoints) { | ||||
| 			pathWaypoints.push_back(waypoint.position); | ||||
| 		} | ||||
| 		std::vector<PathWaypoint> pathWaypoints = path->pathWaypoints; | ||||
|  | ||||
| 		if (GeneralUtils::GenerateRandomNumber<float_t>(0, 1) < 0.5f) { | ||||
| 			std::reverse(pathWaypoints.begin(), pathWaypoints.end()); | ||||
|   | ||||
| @@ -5,20 +5,19 @@ | ||||
| void WblRobotCitizen::OnStartup(Entity* self) { | ||||
| 	auto movementAIComponent = self->GetComponent<MovementAIComponent>(); | ||||
| 	if (!movementAIComponent) return; | ||||
| 	// movementAIComponent->Resume(); | ||||
| } | ||||
|  | ||||
| void WblRobotCitizen::OnUse(Entity* self, Entity* user) { | ||||
| 	// auto movementAIComponent = self->GetComponent<MovementAIComponent>(); | ||||
| 	// if (!movementAIComponent) movementAIComponent->Pause(); | ||||
| 	auto movementAIComponent = self->GetComponent<MovementAIComponent>(); | ||||
| 	if (movementAIComponent) movementAIComponent->Pause(); | ||||
| 	auto face = NiQuaternion::LookAt(self->GetPosition(), user->GetPosition()); | ||||
| 	self->SetRotation(face); | ||||
| 	auto timer = RenderComponent::PlayAnimation(self, "wave"); | ||||
| 	auto timer = RenderComponent::PlayAnimation(self, "wave", 0.4f); | ||||
| 	self->AddTimer("animation time", timer); | ||||
| } | ||||
|  | ||||
| void WblRobotCitizen::OnTimerDone(Entity* self, std::string timerName) { | ||||
| 	auto movementAIComponent = self->GetComponent<MovementAIComponent>(); | ||||
| 	if (!movementAIComponent) return; | ||||
| 	// movementAIComponent->Resume(); | ||||
| 	movementAIComponent->Resume(); | ||||
| } | ||||
|   | ||||
| @@ -16,57 +16,57 @@ class Level; | ||||
| enum class eWaypointCommandType : uint32_t; | ||||
|  | ||||
| struct WaypointCommand { | ||||
| 	eWaypointCommandType command; | ||||
| 	eWaypointCommandType command{}; | ||||
| 	std::string data; | ||||
| }; | ||||
|  | ||||
|  | ||||
| struct SceneRef { | ||||
| 	std::string filename; | ||||
| 	uint32_t id; | ||||
| 	uint32_t sceneType; //0 = general, 1 = audio? | ||||
| 	uint32_t id{}; | ||||
| 	uint32_t sceneType{}; //0 = general, 1 = audio? | ||||
| 	std::string name; | ||||
| 	NiPoint3 unknown1; | ||||
| 	float unknown2; | ||||
| 	uint8_t color_r; | ||||
| 	uint8_t color_g; | ||||
| 	uint8_t color_b; | ||||
| 	float unknown2{}; | ||||
| 	uint8_t color_r{}; | ||||
| 	uint8_t color_g{}; | ||||
| 	uint8_t color_b{}; | ||||
| 	Level* level; | ||||
| 	std::map<uint32_t, LUTriggers::Trigger*> triggers; | ||||
| }; | ||||
|  | ||||
| struct SceneTransitionInfo { | ||||
| 	uint64_t sceneID; //id of the scene being transitioned to. | ||||
| 	uint64_t sceneID{}; //id of the scene being transitioned to. | ||||
| 	NiPoint3 position; | ||||
| }; | ||||
|  | ||||
| struct SceneTransition { | ||||
| 	std::string name; | ||||
| 	std::vector<SceneTransitionInfo> points; | ||||
| 	float width; | ||||
| 	float width{}; | ||||
| }; | ||||
|  | ||||
| struct MovingPlatformPathWaypoint { | ||||
| 	uint8_t lockPlayer; | ||||
| 	float wait; | ||||
| 	uint8_t lockPlayer{}; | ||||
| 	float wait{}; | ||||
| 	std::string departSound; | ||||
| 	std::string arriveSound; | ||||
| }; | ||||
|  | ||||
| struct CameraPathWaypoint { | ||||
| 	float time; | ||||
| 	float fov; | ||||
| 	float tension; | ||||
| 	float continuity; | ||||
| 	float bias; | ||||
| 	float time{}; | ||||
| 	float fov{}; | ||||
| 	float tension{}; | ||||
| 	float continuity{}; | ||||
| 	float bias{}; | ||||
| }; | ||||
|  | ||||
| struct RacingPathWaypoint { | ||||
| 	uint8_t isResetNode; | ||||
| 	uint8_t isNonHorizontalCamera; | ||||
| 	float planeWidth; | ||||
| 	float planeHeight; | ||||
| 	float shortestDistanceToEnd; | ||||
| 	uint8_t isResetNode{}; | ||||
| 	uint8_t isNonHorizontalCamera{}; | ||||
| 	float planeWidth{}; | ||||
| 	float planeHeight{}; | ||||
| 	float shortestDistanceToEnd{}; | ||||
| }; | ||||
|  | ||||
| struct PathWaypoint { | ||||
| @@ -75,7 +75,7 @@ struct PathWaypoint { | ||||
| 	MovingPlatformPathWaypoint movingPlatform; | ||||
| 	CameraPathWaypoint camera; | ||||
| 	RacingPathWaypoint racing; | ||||
| 	float speed; | ||||
| 	float speed{}; | ||||
| 	std::vector<LDFBaseData*> config; | ||||
| 	std::vector<WaypointCommand> commands; | ||||
| }; | ||||
| @@ -137,49 +137,49 @@ enum class PropertyAchievmentRequired : uint32_t { | ||||
|  | ||||
| struct MovingPlatformPath { | ||||
| 	std::string platformTravelSound; | ||||
| 	uint8_t timeBasedMovement; | ||||
| 	uint8_t timeBasedMovement{}; | ||||
| }; | ||||
|  | ||||
| struct PropertyPath { | ||||
| 	PropertyPathType pathType; | ||||
| 	int32_t price; | ||||
| 	uint32_t rentalTime; | ||||
| 	uint64_t associatedZone; | ||||
| 	PropertyPathType pathType{}; | ||||
| 	int32_t price{}; | ||||
| 	uint32_t rentalTime{}; | ||||
| 	uint64_t associatedZone{}; | ||||
| 	std::string displayName; | ||||
| 	std::string displayDesc; | ||||
| 	PropertyType type; | ||||
| 	uint32_t cloneLimit; | ||||
| 	float repMultiplier; | ||||
| 	PropertyRentalPeriod rentalPeriod; | ||||
| 	PropertyAchievmentRequired achievementRequired; | ||||
| 	PropertyType type{}; | ||||
| 	uint32_t cloneLimit{}; | ||||
| 	float repMultiplier{}; | ||||
| 	PropertyRentalPeriod rentalPeriod{}; | ||||
| 	PropertyAchievmentRequired achievementRequired{}; | ||||
|  | ||||
| 	// Player respawn coordinates in the main zone (not the property zone) | ||||
| 	NiPoint3 playerZoneCoords; | ||||
| 	float maxBuildHeight; | ||||
| 	float maxBuildHeight{}; | ||||
| }; | ||||
|  | ||||
| struct CameraPath { | ||||
| 	std::string nextPath; | ||||
| 	uint8_t rotatePlayer; | ||||
| 	uint8_t rotatePlayer{}; | ||||
| }; | ||||
|  | ||||
| struct SpawnerPath { | ||||
| 	LOT spawnedLOT; | ||||
| 	uint32_t respawnTime; | ||||
| 	int32_t maxToSpawn; | ||||
| 	uint32_t amountMaintained; | ||||
| 	LOT spawnedLOT{}; | ||||
| 	uint32_t respawnTime{}; | ||||
| 	int32_t maxToSpawn{}; | ||||
| 	uint32_t amountMaintained{}; | ||||
| 	LWOOBJID spawnerObjID; | ||||
| 	uint8_t spawnerNetActive; | ||||
| 	uint8_t spawnerNetActive{}; | ||||
| }; | ||||
|  | ||||
|  | ||||
| struct Path { | ||||
| 	uint32_t pathVersion; | ||||
| 	uint32_t pathVersion{}; | ||||
| 	PathType pathType; | ||||
| 	std::string pathName; | ||||
| 	uint32_t flags; | ||||
| 	uint32_t flags{}; | ||||
| 	PathBehavior pathBehavior; | ||||
| 	uint32_t waypointCount; | ||||
| 	uint32_t waypointCount{}; | ||||
| 	std::vector<PathWaypoint> pathWaypoints; | ||||
| 	SpawnerPath spawner; | ||||
| 	MovingPlatformPath movingPlatform; | ||||
|   | ||||
| @@ -11,7 +11,7 @@ ALTER TABLE leaderboard CHANGE time secondaryScore FLOAT NOT NULL DEFAULT 0 AFTE | ||||
| /* A bit messy, but better than going through a bunch of code fixes all to be run once. */ | ||||
| UPDATE leaderboard SET | ||||
| 	primaryScore = secondaryScore, | ||||
| 	secondaryScore = 0 WHERE game_id IN (1, 44, 46, 47, 48, 49, 53, 103, 104, 108, 1901); | ||||
| 	secondaryScore = 0 WHERE game_id IN (1, 44, 46, 47, 48, 49, 53, 103, 104, 108, 1901) AND secondaryScore > 0; | ||||
|  | ||||
| /* Do this last so we dont update entry times erroneously */ | ||||
| ALTER TABLE leaderboard  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 jadebenn
					jadebenn