Code changes for region maps (Water!), additional lua functions
Issue #71 - Region Maps support water! Later on to add lava/no fly/other potential regions - new LUA functions: * InWater(spawn) * HasControlEffect(spawn, type) * GetBaseAggroRadius(spawn) * GetAggroRadius(spawn) * SetAggroRadius(spawn, distance, override) - override true sets base to this, otherwise its temporary and doesn't impact GetBaseAggroRadius * SetDeity(spawn, value)
This commit is contained in:
parent
cda936ad3f
commit
9290bceb60
27 changed files with 831 additions and 96 deletions
|
@ -14,6 +14,6 @@ add_executable(eq2world ${WORLD_SRCS} ${COMMON_SRCS} ${LUA_SRCS})
|
|||
|
||||
set(RECAST_LIBRARIES -L${CMAKE_SOURCE_DIR}/EQ2/source/depends/recastnavigation/RecastDemo/Build/gmake/lib/Debug -lDebugUtils -lDetour -lDetourCrowd -lDetourTileCache -lRecast)
|
||||
|
||||
target_include_directories(eq2world PUBLIC ${MySQL_INCLUDE_DIRS} ../common/ ../depends/recastnavigation/Detour/Include)
|
||||
target_include_directories(eq2world PUBLIC ${MySQL_INCLUDE_DIRS} ../common/ ../depends/recastnavigation/Detour/Include ../depends/)
|
||||
target_link_libraries(eq2world PUBLIC ${MySQL_LIBRARIES} ${ZLIB_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${RECAST_LIBRARIES})
|
||||
|
||||
|
|
|
@ -3545,6 +3545,24 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
|
|||
client->Message(CHANNEL_COLOR_YELLOW, "Best Z for %s is %f", spawn->GetName(), bestZ);
|
||||
break;
|
||||
}
|
||||
else if (ToLower(string(sep->arg[0])) == "inwater")
|
||||
{
|
||||
glm::vec3 targPosZ(cmdTarget->GetX(), cmdTarget->GetZ(), cmdTarget->GetY());
|
||||
float bestZ = client->GetPlayer()->FindDestGroundZ(targPosZ, cmdTarget->GetYOffset());
|
||||
if ( bestZ == BEST_Z_INVALID )
|
||||
bestZ = -999999.0f;
|
||||
|
||||
glm::vec3 targPos(cmdTarget->GetY(), cmdTarget->GetX(), cmdTarget->GetZ());
|
||||
|
||||
if (client->GetCurrentZone()->regionmap == nullptr)
|
||||
client->SimpleMessage(CHANNEL_COLOR_RED, "No water map for zone.");
|
||||
else
|
||||
{
|
||||
bool inWater = cmdTarget->InWater();
|
||||
client->Message(CHANNEL_COLOR_YELLOW, "%s is %s.", cmdTarget->GetName(), inWater ? "in water" : "out of water");
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (ToLower(string(sep->arg[0])) == "pathto")
|
||||
{
|
||||
|
||||
|
@ -4011,9 +4029,18 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
|
|||
client->SimpleMessage(CHANNEL_ERROR,"Unable to flag character. Unknown reason.");
|
||||
}
|
||||
}else{
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW,"Usage: /flag {name} {new_status}");
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW," Standard User: 0");
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW," Admin User: 100");
|
||||
sint16 status = database.GetCharacterAdminStatus(client->GetPlayer()->GetName());
|
||||
if(status != client->GetAdminStatus())
|
||||
{
|
||||
client->Message(CHANNEL_COLOR_YELLOW,"Flag status was changed from %i to %i.",status,client->GetAdminStatus());
|
||||
client->SetAdminStatus(status);
|
||||
}
|
||||
else
|
||||
{
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW,"Usage: /flag {name} {new_status}");
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW," Standard User: 0");
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW," Admin User: 100");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -2526,6 +2526,18 @@ void Entity::AddSkillBonus(int32 spell_id, int32 skill_id, float value) {
|
|||
return;
|
||||
}
|
||||
|
||||
bool Entity::HasControlEffect(int8 type)
|
||||
{
|
||||
if (type >= CONTROL_MAX_EFFECTS)
|
||||
return false;
|
||||
|
||||
MutexList<LuaSpell*>* spell_list = control_effects[type];
|
||||
if (!spell_list || spell_list->size(true) == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Entity::HaltMovement()
|
||||
{
|
||||
this->ClearRunningLocations();
|
||||
|
|
|
@ -661,6 +661,8 @@ public:
|
|||
bool IsSnared();
|
||||
float GetHighestSnare();
|
||||
|
||||
bool HasControlEffect(int8 type);
|
||||
|
||||
void HaltMovement();
|
||||
|
||||
|
||||
|
|
|
@ -2399,6 +2399,92 @@ int EQ2Emu_lua_RemoveControlEffect(lua_State* state) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_HasControlEffect(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
Spawn* spawn = lua_interface->GetSpawn(state);
|
||||
int8 type = lua_interface->GetInt8Value(state, 2);
|
||||
|
||||
bool hasEffect = false;
|
||||
|
||||
if (!spawn)
|
||||
lua_interface->LogError("%s: LUA HasControlEffect error: Could not find spawn.", lua_interface->GetScriptName(state));
|
||||
else if (!spawn->IsEntity())
|
||||
lua_interface->LogError("%s: LUA HasControlEffect error: spawn %s is not an entity!.", lua_interface->GetScriptName(state), spawn->GetName());
|
||||
else if (type < CONTROL_MAX_EFFECTS)
|
||||
hasEffect = ((Entity*)spawn)->HasControlEffect(type);
|
||||
else
|
||||
lua_interface->LogError("%s: LUA HasControlEffect unhandled control effect type of %u.", lua_interface->GetScriptName(state), type);
|
||||
|
||||
lua_interface->SetBooleanValue(state, hasEffect);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_GetBaseAggroRadius(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
Spawn* spawn = lua_interface->GetSpawn(state);
|
||||
|
||||
float distance = 0.0f;
|
||||
|
||||
if (!spawn)
|
||||
lua_interface->LogError("%s: LUA GetBaseAggroRadius error: Could not find spawn.", lua_interface->GetScriptName(state));
|
||||
else if (!spawn->IsNPC())
|
||||
lua_interface->LogError("%s: LUA GetBaseAggroRadius error: spawn %s is not an NPC!.", lua_interface->GetScriptName(state), spawn->GetName());
|
||||
else
|
||||
distance = ((NPC*)spawn)->GetBaseAggroRadius();
|
||||
|
||||
lua_interface->SetFloatValue(state, distance);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_GetAggroRadius(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
Spawn* spawn = lua_interface->GetSpawn(state);
|
||||
|
||||
float distance = 0.0f;
|
||||
|
||||
if (!spawn)
|
||||
lua_interface->LogError("%s: LUA GetAggroRadius error: Could not find spawn.", lua_interface->GetScriptName(state));
|
||||
else if (!spawn->IsNPC())
|
||||
lua_interface->LogError("%s: LUA GetAggroRadius error: spawn %s is not an NPC!.", lua_interface->GetScriptName(state), spawn->GetName());
|
||||
else
|
||||
distance = ((NPC*)spawn)->GetAggroRadius();
|
||||
|
||||
lua_interface->SetFloatValue(state, distance);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_SetAggroRadius(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
Spawn* spawn = lua_interface->GetSpawn(state);
|
||||
float distance = lua_interface->GetFloatValue(state, 2);
|
||||
bool override = lua_interface->GetBooleanValue(state, 3);
|
||||
|
||||
bool result = false;
|
||||
|
||||
lua_interface->ResetFunctionStack(state);
|
||||
|
||||
if (!spawn)
|
||||
lua_interface->LogError("%s: LUA SetAggroRadius error: Could not find spawn.", lua_interface->GetScriptName(state));
|
||||
else if (!spawn->IsNPC())
|
||||
lua_interface->LogError("%s: LUA SetAggroRadius error: spawn %s is not an NPC!.", lua_interface->GetScriptName(state), spawn->GetName());
|
||||
else
|
||||
{
|
||||
((NPC*)spawn)->SetAggroRadius(distance, override);
|
||||
result = true;
|
||||
}
|
||||
|
||||
lua_interface->SetBooleanValue(state, result);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_SetIntBase(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
|
@ -2464,6 +2550,34 @@ int EQ2Emu_lua_SetStrBase(lua_State* state) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_SetDeity(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
Spawn* spawn = lua_interface->GetSpawn(state);
|
||||
int8 value = lua_interface->GetInt8Value(state, 2);
|
||||
if (spawn && spawn->IsEntity()) {
|
||||
((Entity*)spawn)->SetDeity(value);
|
||||
if (spawn->IsPlayer())
|
||||
((Player*)spawn)->SetCharSheetChanged(true);
|
||||
}
|
||||
|
||||
lua_interface->ResetFunctionStack(state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_GetDeity(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
Spawn* spawn = lua_interface->GetSpawn(state);
|
||||
if (spawn && spawn->IsEntity()) {
|
||||
int8 deity = ((Entity*)spawn)->GetDeity();
|
||||
lua_interface->SetInt32Value(state, deity);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int EQ2Emu_lua_SetInt(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
|
@ -10785,4 +10899,15 @@ int EQ2Emu_lua_CastCustomSpell(lua_State* state) {
|
|||
|
||||
target->GetZone()->ProcessSpell(NULL, (Entity*)caster, (Entity*)target, true, false, spell, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_InWater(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
Spawn* spawn = lua_interface->GetSpawn(state);
|
||||
if (spawn) {
|
||||
lua_interface->SetBooleanValue(state, spawn->InWater());
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -54,6 +54,15 @@ int EQ2Emu_lua_AddSkillBonus(lua_State* state);
|
|||
int EQ2Emu_lua_RemoveSkillBonus(lua_State* state);
|
||||
int EQ2Emu_lua_AddControlEffect(lua_State* state);
|
||||
int EQ2Emu_lua_RemoveControlEffect(lua_State* state);
|
||||
int EQ2Emu_lua_HasControlEffect(lua_State* state);
|
||||
|
||||
int EQ2Emu_lua_GetBaseAggroRadius(lua_State* state);
|
||||
int EQ2Emu_lua_GetAggroRadius(lua_State* state);
|
||||
int EQ2Emu_lua_SetAggroRadius(lua_State* state);
|
||||
|
||||
int EQ2Emu_lua_SetDeity(lua_State* state);
|
||||
int EQ2Emu_lua_GetDeity(lua_State* state);
|
||||
|
||||
int EQ2Emu_lua_SetInt(lua_State* state);
|
||||
int EQ2Emu_lua_SetWis(lua_State* state);
|
||||
int EQ2Emu_lua_SetSta(lua_State* state);
|
||||
|
@ -490,4 +499,6 @@ int EQ2Emu_lua_GetSpellDataIndex(lua_State* state);
|
|||
|
||||
int EQ2Emu_lua_SetSpellDisplayEffect(lua_State* state);
|
||||
int EQ2Emu_lua_GetSpellDisplayEffect(lua_State* state);
|
||||
|
||||
int EQ2Emu_lua_InWater(lua_State* state);
|
||||
#endif
|
|
@ -775,7 +775,19 @@ void LuaInterface::RegisterFunctions(lua_State* state) {
|
|||
lua_register(state, "RemoveSkillBonus", EQ2Emu_lua_RemoveSkillBonus);
|
||||
lua_register(state, "AddControlEffect", EQ2Emu_lua_AddControlEffect);
|
||||
lua_register(state, "RemoveControlEffect", EQ2Emu_lua_RemoveControlEffect);
|
||||
lua_register(state, "HasControlEffect", EQ2Emu_lua_HasControlEffect);
|
||||
|
||||
lua_register(state, "GetBaseAggroRadius", EQ2Emu_lua_GetBaseAggroRadius);
|
||||
lua_register(state, "GetAggroRadius", EQ2Emu_lua_GetAggroRadius);
|
||||
lua_register(state, "SetAggroRadius", EQ2Emu_lua_SetAggroRadius);
|
||||
|
||||
lua_register(state, "GetCurrentZoneSafeLocation", EQ2Emu_lua_GetCurrentZoneSafeLocation);
|
||||
|
||||
|
||||
lua_register(state, "SetDeity", EQ2Emu_lua_SetDeity);
|
||||
lua_register(state, "GetDeity", EQ2Emu_lua_GetDeity);
|
||||
|
||||
|
||||
lua_register(state, "GetInt", EQ2Emu_lua_GetInt);
|
||||
lua_register(state, "GetWis", EQ2Emu_lua_GetWis);
|
||||
lua_register(state, "GetSta", EQ2Emu_lua_GetSta);
|
||||
|
@ -1119,6 +1131,8 @@ void LuaInterface::RegisterFunctions(lua_State* state) {
|
|||
|
||||
lua_register(state, "SetSpellDisplayEffect", EQ2Emu_lua_SetSpellDisplayEffect);
|
||||
lua_register(state, "GetSpellDisplayEffect", EQ2Emu_lua_GetSpellDisplayEffect);
|
||||
|
||||
lua_register(state, "InWater", EQ2Emu_lua_InWater);
|
||||
}
|
||||
|
||||
void LuaInterface::LogError(const char* error, ...) {
|
||||
|
|
|
@ -83,7 +83,7 @@ NPC::NPC(NPC* old_npc){
|
|||
SetPrimarySkillList(old_npc->GetPrimarySkillList());
|
||||
SetSecondarySkillList(old_npc->GetSecondarySkillList());
|
||||
SetEquipmentListID(old_npc->GetEquipmentListID());
|
||||
SetAggroRadius(old_npc->GetAggroRadius());
|
||||
SetAggroRadius(old_npc->GetBaseAggroRadius());
|
||||
SetCastPercentage(old_npc->GetCastPercentage());
|
||||
SetRandomize(old_npc->GetRandomize());
|
||||
if(appearance.randomize > 0)
|
||||
|
@ -125,7 +125,8 @@ void NPC::Initialize(){
|
|||
attack_resume_needed = false;
|
||||
MMovementLoop.SetName("NPC::MMovementLoop");
|
||||
last_movement_update = Timer::GetCurrentTime2();
|
||||
aggro_radius = 0;
|
||||
aggro_radius = 0.0f;
|
||||
base_aggro_radius = 0.0f;
|
||||
skills = 0;
|
||||
spells = 0;
|
||||
runback = 0;
|
||||
|
@ -192,7 +193,7 @@ void NPC::Runback(){
|
|||
m_runningBack = true;
|
||||
SetSpeed(GetMaxSpeed()*2);
|
||||
|
||||
if (IsFlying() && CheckLoS(glm::vec3(runback->x, runback->z, runback->y + 1.0f), glm::vec3(GetX(), GetZ(), GetY() + 1.0f)))
|
||||
if ((IsFlyingCreature() || IsWaterCreature()) && CheckLoS(glm::vec3(runback->x, runback->z, runback->y + 1.0f), glm::vec3(GetX(), GetZ(), GetY() + 1.0f)))
|
||||
{
|
||||
FaceTarget(runback->x, runback->z);
|
||||
ClearRunningLocations();
|
||||
|
@ -775,7 +776,10 @@ Spell* NPC::GetNextBuffSpell() {
|
|||
return ret;
|
||||
}
|
||||
|
||||
void NPC::SetAggroRadius(float radius){
|
||||
void NPC::SetAggroRadius(float radius, bool overrideBaseValue){
|
||||
if (base_aggro_radius == 0.0f || overrideBaseValue)
|
||||
base_aggro_radius = radius;
|
||||
|
||||
aggro_radius = radius;
|
||||
}
|
||||
|
||||
|
|
|
@ -104,8 +104,9 @@ public:
|
|||
int32 GetEquipmentListID();
|
||||
Spell* GetNextSpell(float distance);
|
||||
virtual Spell* GetNextBuffSpell();
|
||||
void SetAggroRadius(float radius);
|
||||
void SetAggroRadius(float radius, bool overrideBaseValue = false);
|
||||
float GetAggroRadius();
|
||||
float GetBaseAggroRadius() { return base_aggro_radius; }
|
||||
void SetCastPercentage(int8 percentage);
|
||||
int8 GetCastPercentage();
|
||||
void SetSkills(map<string, Skill*>* in_skills);
|
||||
|
@ -148,6 +149,7 @@ private:
|
|||
MovementLocation* runback;
|
||||
int8 cast_percentage;
|
||||
float aggro_radius;
|
||||
float base_aggro_radius;
|
||||
Spell* GetNextSpell(float distance, int8 type);
|
||||
map<string, Skill*>* skills;
|
||||
vector<Spell*>* spells;
|
||||
|
|
|
@ -82,8 +82,11 @@ void Brain::Think() {
|
|||
}
|
||||
m_body->FaceTarget(target);
|
||||
|
||||
bool breakWaterPursuit = false;
|
||||
if (m_body->IsWaterCreature() && !target->InWater())
|
||||
breakWaterPursuit = true;
|
||||
// Check to see if the NPC has exceeded the max chase distance
|
||||
if (run_back_distance > MAX_CHASE_DISTANCE) {
|
||||
if (run_back_distance > MAX_CHASE_DISTANCE || breakWaterPursuit) {
|
||||
LogWrite(NPC_AI__DEBUG, 7, "NPC_AI", "Run back distance is greater then max chase distance, run_back_distance = %f", run_back_distance);
|
||||
// Over the max chase distance, Check to see if the target is is a client
|
||||
Client* client = target->GetZone()->GetClientBySpawn(target);
|
||||
|
|
|
@ -114,6 +114,8 @@ Spawn::Spawn(){
|
|||
pickup_unique_item_id = 0;
|
||||
disable_sounds = false;
|
||||
has_quests_required = false;
|
||||
is_flying_creature = false;
|
||||
is_water_creature = false;
|
||||
}
|
||||
|
||||
Spawn::~Spawn(){
|
||||
|
@ -2614,7 +2616,7 @@ void Spawn::MoveToLocation(Spawn* spawn, float distance, bool immediate, bool ma
|
|||
|
||||
if (!IsPlayer() && distance > 0.0f)
|
||||
{
|
||||
if (IsFlying() && CheckLoS(spawn))
|
||||
if ((IsFlyingCreature() || IsWaterCreature()) && CheckLoS(spawn))
|
||||
{
|
||||
if (immediate)
|
||||
ClearRunningLocations();
|
||||
|
@ -2661,7 +2663,7 @@ void Spawn::ProcessMovement(bool isSpawnListLocked){
|
|||
FixZ(true);
|
||||
|
||||
int32 newGrid = GetZone()->Grid->GetGridID(this);
|
||||
if (!IsFlying() && newGrid != 0 && newGrid != appearance.pos.grid_id)
|
||||
if (!IsFlyingCreature() && newGrid != 0 && newGrid != appearance.pos.grid_id)
|
||||
SetPos(&(appearance.pos.grid_id), newGrid);
|
||||
|
||||
forceMapCheck = false;
|
||||
|
@ -3085,7 +3087,7 @@ bool Spawn::CalculateChange(){
|
|||
}
|
||||
|
||||
int32 newGrid = GetZone()->Grid->GetGridID(this);
|
||||
if (!IsFlying() && newGrid != 0 && newGrid != appearance.pos.grid_id)
|
||||
if (!IsFlyingCreature() && newGrid != 0 && newGrid != appearance.pos.grid_id)
|
||||
SetPos(&(appearance.pos.grid_id), newGrid);
|
||||
}
|
||||
}
|
||||
|
@ -3124,7 +3126,7 @@ void Spawn::CalculateRunningLocation(bool stop){
|
|||
{
|
||||
if (GetDistance(GetTarget()) > rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat())
|
||||
{
|
||||
if (IsFlying() && CheckLoS(GetTarget()))
|
||||
if ((IsFlyingCreature() || IsWaterCreature()) && CheckLoS(GetTarget()))
|
||||
AddRunningLocation(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), GetSpeed(), 0, false);
|
||||
else
|
||||
GetZone()->movementMgr->NavigateTo((Entity*)this, GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ());
|
||||
|
@ -3582,7 +3584,7 @@ float Spawn::GetFixedZ(const glm::vec3& destination, int32 z_find_offset) {
|
|||
|
||||
|
||||
void Spawn::FixZ(bool forceUpdate) {
|
||||
if (IsPlayer() || IsFlying() || !GetZone() || (IsObject() && GetZone()->GetInstanceType() == Instance_Type::PERSONAL_HOUSE_INSTANCE)) {
|
||||
if (IsPlayer() || IsFlyingCreature() || !GetZone() || (IsObject() && GetZone()->GetInstanceType() == Instance_Type::PERSONAL_HOUSE_INSTANCE)) {
|
||||
return;
|
||||
}
|
||||
/*
|
||||
|
@ -3593,9 +3595,22 @@ void Spawn::FixZ(bool forceUpdate) {
|
|||
if (zone->watermap && zone->watermap->InLiquid(m_Position)) {
|
||||
return;
|
||||
}*/
|
||||
|
||||
|
||||
// we do the inwater check here manually to avoid double calling for a Z coordinate
|
||||
glm::vec3 current_loc(GetX(), GetZ(), GetY());
|
||||
float new_z = GetFixedZ(current_loc, 1);
|
||||
|
||||
if ( GetZone()->regionmap != nullptr )
|
||||
{
|
||||
glm::vec3 targPos(GetY(), GetX(), GetZ());
|
||||
float bestZ = -999999.0f;
|
||||
if ( new_z != BEST_Z_INVALID )
|
||||
bestZ = new_z - 1.0f;
|
||||
|
||||
if(GetZone()->regionmap->InWater(targPos, bestZ))
|
||||
return;
|
||||
}
|
||||
|
||||
if (new_z == GetY())
|
||||
return;
|
||||
|
||||
|
@ -3799,4 +3814,28 @@ void Spawn::RemoveSpawnFromPlayer(Player* player)
|
|||
m_Update.writelock(__FUNCTION__, __LINE__);
|
||||
player->RemoveSpawn(this); // sets it as removed
|
||||
m_Update.releasewritelock(__FUNCTION__, __LINE__);
|
||||
}
|
||||
|
||||
bool Spawn::InWater()
|
||||
{
|
||||
bool inWater = false;
|
||||
|
||||
if (GetZone()->regionmap != nullptr)
|
||||
{
|
||||
glm::vec3 current_loc(GetX(), GetZ(), GetY());
|
||||
float new_z = GetFixedZ(current_loc, 1);
|
||||
|
||||
if ( GetZone()->regionmap != nullptr )
|
||||
{
|
||||
glm::vec3 targPos(GetY(), GetX(), GetZ());
|
||||
float bestZ = -999999.0f;
|
||||
if ( new_z != BEST_Z_INVALID )
|
||||
bestZ = new_z;
|
||||
|
||||
if(GetZone()->regionmap->InWater(targPos, bestZ))
|
||||
inWater = true;
|
||||
}
|
||||
}
|
||||
|
||||
return inWater;
|
||||
}
|
|
@ -751,6 +751,8 @@ public:
|
|||
void SetModelType(int16 model_type, bool setUpdateFlags = true){
|
||||
SetInfo(&appearance.model_type, model_type, setUpdateFlags);
|
||||
SetInfo(&appearance.soga_model_type, model_type, setUpdateFlags);
|
||||
SetFlyingCreature();
|
||||
SetWaterCreature();
|
||||
}
|
||||
int16 GetSogaModelType(){
|
||||
return appearance.soga_model_type;
|
||||
|
@ -759,7 +761,37 @@ public:
|
|||
return appearance.model_type;
|
||||
}
|
||||
|
||||
bool IsFlying() { return (GetInitialState() == 49156); }
|
||||
bool IsFlyingCreature() { return is_flying_creature; }
|
||||
bool IsWaterCreature() { return is_water_creature; }
|
||||
bool InWater();
|
||||
|
||||
void SetFlyingCreature() {
|
||||
is_flying_creature = false;
|
||||
switch (GetModelType())
|
||||
{
|
||||
case 260:
|
||||
case 295:
|
||||
is_flying_creature = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SetWaterCreature() {
|
||||
is_water_creature = false;
|
||||
|
||||
switch (GetModelType())
|
||||
{
|
||||
case 194:
|
||||
case 204:
|
||||
case 210:
|
||||
case 241:
|
||||
case 242:
|
||||
case 254:
|
||||
case 20828:
|
||||
is_water_creature = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
void SetPrimaryCommand(const char* name, const char* command, float distance = 10);
|
||||
void SetPrimaryCommands(vector<EntityCommand*>* commands);
|
||||
void SetSecondaryCommands(vector<EntityCommand*>* commands);
|
||||
|
@ -1008,6 +1040,8 @@ public:
|
|||
int32 last_movement_update;
|
||||
int32 last_location_update;
|
||||
bool forceMapCheck;
|
||||
bool is_water_creature;
|
||||
bool is_flying_creature;
|
||||
|
||||
bool following;
|
||||
bool IsPet() { return is_pet; }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "mob_movement_manager.h"
|
||||
#include "../Entity.h"
|
||||
#include "../zoneserver.h"
|
||||
#include "water_map.h"
|
||||
#include "region_map.h"
|
||||
#include "map.h"
|
||||
#include "../../common/timer.h"
|
||||
#include "pathfinder_interface.h"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <DetourCommon.h>
|
||||
#include <DetourNavMeshQuery.h>
|
||||
#include "../zoneserver.h"
|
||||
#include "water_map.h"
|
||||
#include "region_map.h"
|
||||
#include "../client.h"
|
||||
|
||||
struct PathfinderNavmesh::Implementation
|
||||
|
|
67
EQ2/source/WorldServer/Zone/region_map.cpp
Normal file
67
EQ2/source/WorldServer/Zone/region_map.cpp
Normal file
|
@ -0,0 +1,67 @@
|
|||
|
||||
|
||||
#include "region_map.h"
|
||||
#include "region_map_v1.h"
|
||||
#include "../../common/Log.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fstream>
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
inline bool file_exists(const std::string& name) {
|
||||
std::ifstream f(name.c_str());
|
||||
return f.good();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param zone_name
|
||||
* @return
|
||||
*/
|
||||
RegionMap* RegionMap::LoadRegionMapfile(std::string zone_name) {
|
||||
std::string filename = "Regions/";
|
||||
filename += zone_name;
|
||||
filename += ".EQ2Region";
|
||||
FILE* f = fopen(filename.c_str(), "rb");
|
||||
|
||||
LogWrite(REGION__DEBUG, 7, "Region", "Attempting load of %s", filename.c_str());
|
||||
|
||||
if (!f)
|
||||
{
|
||||
LogWrite(REGION__ERROR, 7, "Region", "Failed to load of %s", filename.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Read the string for the zone file name this was created for
|
||||
int8 strSize;
|
||||
char name[256];
|
||||
fread(&strSize, sizeof(int8), 1, f);
|
||||
LogWrite(REGION__DEBUG, 7, "Region", "strSize = %u", strSize);
|
||||
|
||||
size_t len = fread(&name, sizeof(char), strSize, f);
|
||||
name[len] = '\0';
|
||||
LogWrite(REGION__DEBUG, 7, "Region", "name = %s", name);
|
||||
|
||||
string fileName(name);
|
||||
std::size_t found = fileName.find(zone_name);
|
||||
// Make sure file contents are for the correct zone
|
||||
if (found == std::string::npos) {
|
||||
fclose(f);
|
||||
LogWrite(REGION__ERROR, 0, "Region", "WaterMap::LoadWaterMapfile() map contents (%s) do not match its name (%s).", &name, zone_name.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int32 regionMapVersion;
|
||||
fread(®ionMapVersion, sizeof(int32), 1, f);
|
||||
LogWrite(REGION__INFO, 0, "Region", "Loading %s RegionMapVersion = %u", name, regionMapVersion);
|
||||
|
||||
RegionMapV1* regionmap = new RegionMapV1();
|
||||
regionmap->Load(f);
|
||||
|
||||
return regionmap;
|
||||
}
|
48
EQ2/source/WorldServer/Zone/region_map.h
Normal file
48
EQ2/source/WorldServer/Zone/region_map.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
#ifndef EQ2EMU_REGION_MAP_H
|
||||
#define EQ2EMU_REGION_MAP_H
|
||||
|
||||
#include "../../common/types.h"
|
||||
#include "position.h"
|
||||
#include <string>
|
||||
|
||||
enum WaterRegionType : int {
|
||||
RegionTypeUnsupported = -2,
|
||||
RegionTypeUntagged = -1,
|
||||
RegionTypeNormal = 0,
|
||||
RegionTypeWater = 1,
|
||||
RegionTypeLava = 2,
|
||||
RegionTypeZoneLine = 3,
|
||||
RegionTypePVP = 4,
|
||||
RegionTypeSlime = 5,
|
||||
RegionTypeIce = 6,
|
||||
RegionTypeVWater = 7
|
||||
};
|
||||
|
||||
enum WaterRegionClass : int32 {
|
||||
ClassWaterVolume = 0, // matching .region file type by name "watervol"
|
||||
ClassWaterRegion = 1, // matching .region file type by name "waterregion"
|
||||
ClassWaterRegion2 = 2, // represents .region file name "water_region" potentially defunct and just a WaterVolume (0)
|
||||
ClassWaterOcean = 3, // represents .region file with "ocean" and a select node as a parent
|
||||
ClassWaterCavern = 4, // represents .region file with matches on name "ocean" and "water"
|
||||
ClassWaterOcean2 = 5 // represents .region file with matches on name "ocean" without previous matches (no select node parent and no water string match)
|
||||
};
|
||||
|
||||
class RegionMap
|
||||
{
|
||||
public:
|
||||
RegionMap() { }
|
||||
virtual ~RegionMap() { }
|
||||
|
||||
static RegionMap* LoadRegionMapfile(std::string zone_name);
|
||||
virtual WaterRegionType ReturnRegionType(const glm::vec3& location, float belowY = -999999.0f) const = 0;
|
||||
virtual bool InWater(const glm::vec3& location, float belowY = -999999.0f) const = 0;
|
||||
virtual bool InLava(const glm::vec3& location) const = 0;
|
||||
virtual bool InLiquid(const glm::vec3& location) const = 0;
|
||||
virtual bool InPvP(const glm::vec3& location) const = 0;
|
||||
virtual bool InZoneLine(const glm::vec3& location) const = 0;
|
||||
|
||||
protected:
|
||||
virtual bool Load(FILE *fp) { return false; }
|
||||
};
|
||||
|
||||
#endif
|
323
EQ2/source/WorldServer/Zone/region_map_v1.cpp
Normal file
323
EQ2/source/WorldServer/Zone/region_map_v1.cpp
Normal file
|
@ -0,0 +1,323 @@
|
|||
#include "region_map_v1.h"
|
||||
#include "../../common/Log.h"
|
||||
|
||||
RegionMapV1::RegionMapV1() {
|
||||
|
||||
}
|
||||
|
||||
RegionMapV1::~RegionMapV1() {
|
||||
map<Region_Node*, ZBSP_Node*>::const_iterator itr;
|
||||
int region_num = 0;
|
||||
for (itr = Regions.begin(); itr != Regions.end();)
|
||||
{
|
||||
Region_Node* node = itr->first;
|
||||
ZBSP_Node* bsp_node = itr->second;
|
||||
map<Region_Node*, ZBSP_Node*>::const_iterator deleteItr = itr;
|
||||
itr++;
|
||||
Regions.erase(deleteItr);
|
||||
safe_delete(node);
|
||||
safe_delete(bsp_node);
|
||||
}
|
||||
|
||||
Regions.clear();
|
||||
}
|
||||
|
||||
WaterRegionType RegionMapV1::ReturnRegionType(const glm::vec3& location, float belowY) const {
|
||||
return BSPReturnRegionType(1, glm::vec3(location.y, location.x + 0.5f, location.z));
|
||||
}
|
||||
|
||||
bool RegionMapV1::InWater(const glm::vec3& location, float belowY) const {
|
||||
return ReturnRegionType(location, belowY) == RegionTypeWater;
|
||||
}
|
||||
|
||||
bool RegionMapV1::InLava(const glm::vec3& location) const {
|
||||
return ReturnRegionType(location) == RegionTypeLava;
|
||||
}
|
||||
|
||||
bool RegionMapV1::InLiquid(const glm::vec3& location) const {
|
||||
return InWater(location) || InLava(location);
|
||||
}
|
||||
|
||||
bool RegionMapV1::InPvP(const glm::vec3& location) const {
|
||||
return ReturnRegionType(location) == RegionTypePVP;
|
||||
}
|
||||
|
||||
bool RegionMapV1::InZoneLine(const glm::vec3& location) const {
|
||||
return ReturnRegionType(location) == RegionTypeZoneLine;
|
||||
}
|
||||
|
||||
bool RegionMapV1::Load(FILE* fp) {
|
||||
uint32 region_size;
|
||||
if (fread(®ion_size, sizeof(region_size), 1, fp) != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LogWrite(REGION__DEBUG, 0, "RegionMap", "region count = %u", region_size);
|
||||
|
||||
for (int i = 0; i < region_size; i++)
|
||||
{
|
||||
uint32 region_num;
|
||||
if (fread(®ion_num, sizeof(region_num), 1, fp) != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 region_type;
|
||||
if (fread(®ion_type, sizeof(region_type), 1, fp) != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float x, y, z, dist;
|
||||
if (fread(&x, sizeof(x), 1, fp) != 1) {
|
||||
return false;
|
||||
}
|
||||
if (fread(&y, sizeof(y), 1, fp) != 1) {
|
||||
return false;
|
||||
}
|
||||
if (fread(&z, sizeof(z), 1, fp) != 1) {
|
||||
return false;
|
||||
}
|
||||
if (fread(&dist, sizeof(dist), 1, fp) != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 bsp_tree_size;
|
||||
if (fread(&bsp_tree_size, sizeof(bsp_tree_size), 1, fp) != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LogWrite(REGION__DEBUG, 0, "RegionMap", "region x,y,z,dist = %f, %f, %f, %f, region bsp tree size: %u", x, y, z, dist, bsp_tree_size);
|
||||
|
||||
ZBSP_Node* BSP_Root = new ZBSP_Node[bsp_tree_size];
|
||||
if (fread(BSP_Root, sizeof(ZBSP_Node), bsp_tree_size, fp) != bsp_tree_size) {
|
||||
LogWrite(REGION__ERROR, 0, "RegionMap", "Failed to load region.");
|
||||
return false;
|
||||
}
|
||||
|
||||
Region_Node* tmpNode = new Region_Node;
|
||||
tmpNode->x = x;
|
||||
tmpNode->y = y;
|
||||
tmpNode->z = z;
|
||||
tmpNode->dist = dist;
|
||||
tmpNode->region_type = region_type;
|
||||
Regions.insert(make_pair(tmpNode, BSP_Root));
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
LogWrite(REGION__DEBUG, 0, "RegionMap", "completed load!");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
WaterRegionType RegionMapV1::BSPReturnRegionType(int32 node_number, const glm::vec3& location) const {
|
||||
map<Region_Node*, ZBSP_Node*>::const_iterator itr;
|
||||
int region_num = 0;
|
||||
for (itr = Regions.begin(); itr != Regions.end(); itr++)
|
||||
{
|
||||
Region_Node* node = itr->first;
|
||||
ZBSP_Node* BSP_Root = itr->second;
|
||||
|
||||
float x1 = node->x - location.x;
|
||||
float y1 = node->y - location.y;
|
||||
float z1 = node->z - location.z;
|
||||
float dist = sqrt(x1 * x1 + y1 * y1 + z1 * z1);
|
||||
|
||||
#ifdef REGIONDEBUG
|
||||
printf("Region %i (%i) dist %f / node dist %f. NodeXYZ: %f %f %f, XYZ: %f %f %f.\n", region_num, node->region_type, dist, node->dist, node->x, node->y, node->z, location.x, location.y, location.z);
|
||||
#endif
|
||||
|
||||
if (dist <= node->dist)
|
||||
{
|
||||
ZBSP_Node* BSP_Root = itr->second;
|
||||
const ZBSP_Node* current_node = &BSP_Root[node_number - 1];
|
||||
|
||||
WaterRegionType regionType = RegionTypeUntagged;
|
||||
|
||||
if (node->region_type == ClassWaterRegion)
|
||||
regionType = BSPReturnRegionWaterRegion(node, BSP_Root, node_number, location, dist);
|
||||
else
|
||||
regionType = BSPReturnRegionTypeNode(node, BSP_Root, node_number, location, dist);
|
||||
|
||||
if (regionType != RegionTypeNormal)
|
||||
return regionType;
|
||||
}
|
||||
region_num++;
|
||||
}
|
||||
|
||||
return(RegionTypeNormal);
|
||||
}
|
||||
|
||||
WaterRegionType RegionMapV1::BSPReturnRegionTypeNode(const Region_Node* region_node, const ZBSP_Node* BSP_Root, int32 node_number, const glm::vec3& location, float distToNode) const {
|
||||
const ZBSP_Node* current_node = &BSP_Root[node_number - 1];
|
||||
float distance;
|
||||
|
||||
#ifdef REGIONDEBUG
|
||||
printf("left = %u, right %u\n", current_node->left, current_node->right);
|
||||
#endif
|
||||
|
||||
if (region_node->region_type == ClassWaterRegion2)
|
||||
{
|
||||
distance = (location.x * current_node->normal[0]) +
|
||||
(location.y * current_node->normal[1]) +
|
||||
(location.z * current_node->normal[2]) +
|
||||
current_node->splitdistance;
|
||||
}
|
||||
else {
|
||||
distance = (location.x * current_node->normal[0]) +
|
||||
(location.y * current_node->normal[1]) +
|
||||
(location.z * current_node->normal[2]) -
|
||||
current_node->splitdistance;
|
||||
}
|
||||
|
||||
float absDistance = distance;
|
||||
if (absDistance < 0.0f)
|
||||
absDistance *= -1.0f;
|
||||
|
||||
float absSplitDist = current_node->splitdistance;
|
||||
if (absSplitDist < 0.0f)
|
||||
absSplitDist *= -1.0f;
|
||||
|
||||
#ifdef REGIONDEBUG
|
||||
printf("distance = %f, normals: %f %f %f, location: %f %f %f, split distance: %f\n", distance, current_node->left, current_node->right, current_node->normal[0], current_node->normal[1], current_node->normal[2],
|
||||
location.x, location.y, location.z, current_node->splitdistance);
|
||||
#endif
|
||||
|
||||
if ((current_node->left == 4294967294) &&
|
||||
(current_node->right == 4294967295)) {
|
||||
if (region_node->region_type == ClassWaterOcean || region_node->region_type == ClassWaterOcean2)
|
||||
{
|
||||
return EstablishDistanceAtAngle(region_node, current_node, distance, absDistance, absSplitDist, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (distance > 0)
|
||||
return(RegionTypeWater);
|
||||
else
|
||||
return RegionTypeNormal;
|
||||
}
|
||||
}
|
||||
else if ((region_node->region_type == ClassWaterOcean || region_node->region_type == ClassWaterOcean2) && current_node->normal[1] != 1.0f && current_node->normal[1] != -1.0f)
|
||||
{
|
||||
float fraction = abs(current_node->normal[0] * current_node->normal[2]);
|
||||
float diff = distToNode / region_node->dist;
|
||||
if (distance > 0)
|
||||
diff = distance * diff;
|
||||
|
||||
#ifdef REGIONDEBUG
|
||||
printf("Diff: %f (%f + %f), fraction %f\n", diff, distToNode, distance, fraction);
|
||||
#endif
|
||||
if ((abs(diff) / 2.0f) > (absSplitDist * (1.0f / fraction)) * 2.0f)
|
||||
return RegionTypeNormal;
|
||||
}
|
||||
|
||||
if (distance == 0.0f) {
|
||||
return(RegionTypeNormal);
|
||||
}
|
||||
|
||||
if (distance > 0.0f) {
|
||||
|
||||
#ifdef REGIONDEBUG
|
||||
printf("to left node %i\n", current_node->left);
|
||||
#endif
|
||||
if (current_node->left == 4294967294 && ((region_node->region_type == ClassWaterVolume || region_node->region_type == ClassWaterOcean2) ||
|
||||
(region_node->region_type == ClassWaterOcean && current_node->normal[1] == 1.0f)))
|
||||
return RegionTypeWater;
|
||||
else if (current_node->left == -1 || current_node->left == -2) {
|
||||
if (current_node->left == -2 && region_node->region_type == ClassWaterCavern)
|
||||
return EstablishDistanceAtAngle(region_node, current_node, distance, absDistance, absSplitDist, true);
|
||||
else
|
||||
return(RegionTypeNormal);
|
||||
}
|
||||
return BSPReturnRegionTypeNode(region_node, BSP_Root, current_node->left + 1, location, distToNode);
|
||||
}
|
||||
|
||||
#ifdef REGIONDEBUG
|
||||
printf("to right node %i, sign bit %i\n", current_node->right, signbit(current_node->normal[1]));
|
||||
#endif
|
||||
if (current_node->right == -1) {
|
||||
if (region_node->region_type == ClassWaterOcean2 && signbit(current_node->normal[1]) == 0 && absDistance < absSplitDist)
|
||||
return RegionTypeWater;
|
||||
else if ((region_node->region_type == ClassWaterOcean || region_node->region_type == ClassWaterOcean2) &&
|
||||
(current_node->normal[1] > 0.0f && distance < 0.0f && absDistance < absSplitDist))
|
||||
{
|
||||
return(RegionTypeWater);
|
||||
}
|
||||
return(RegionTypeNormal);
|
||||
}
|
||||
|
||||
return BSPReturnRegionTypeNode(region_node, BSP_Root, current_node->right + 1, location, distToNode);
|
||||
}
|
||||
|
||||
|
||||
WaterRegionType RegionMapV1::BSPReturnRegionWaterRegion(const Region_Node* region_node, const ZBSP_Node* BSP_Root, int32 node_number, const glm::vec3& location, float distToNode) const {
|
||||
const ZBSP_Node* current_node = &BSP_Root[node_number - 1];
|
||||
float distance;
|
||||
|
||||
#ifdef REGIONDEBUG
|
||||
printf("left = %u, right %u\n", current_node->left, current_node->right);
|
||||
#endif
|
||||
|
||||
distance = (location.x * current_node->normal[0]) +
|
||||
(location.y * current_node->normal[1]) +
|
||||
(location.z * current_node->normal[2]) -
|
||||
current_node->splitdistance;
|
||||
|
||||
#ifdef REGIONDEBUG
|
||||
printf("distance = %f, normals: %f %f %f, location: %f %f %f, split distance: %f\n", distance, current_node->left, current_node->right, current_node->normal[0], current_node->normal[1], current_node->normal[2],
|
||||
location.x, location.y, location.z, current_node->splitdistance);
|
||||
#endif
|
||||
|
||||
if (distance > 0.0f) {
|
||||
#ifdef REGIONDEBUG
|
||||
printf("to left node %i\n", current_node->left);
|
||||
#endif
|
||||
if (current_node->left == -1) {
|
||||
return(RegionTypeNormal);
|
||||
}
|
||||
else if (current_node->left == 4294967294) {
|
||||
return(RegionTypeWater);
|
||||
}
|
||||
return BSPReturnRegionWaterRegion(region_node, BSP_Root, current_node->left + 1, location, distToNode);
|
||||
}
|
||||
|
||||
#ifdef REGIONDEBUG
|
||||
printf("to right node %i, sign bit %i\n", current_node->right, signbit(current_node->normal[1]));
|
||||
#endif
|
||||
|
||||
if (current_node->right == -1) {
|
||||
return(RegionTypeNormal);
|
||||
}
|
||||
|
||||
return BSPReturnRegionWaterRegion(region_node, BSP_Root, current_node->right + 1, location, distToNode);
|
||||
}
|
||||
|
||||
WaterRegionType RegionMapV1::EstablishDistanceAtAngle(const Region_Node* region_node, const ZBSP_Node* current_node, float distance, float absDistance, float absSplitDist, bool checkEdgedAngle) const {
|
||||
float fraction = abs(current_node->normal[0] * current_node->normal[2]);
|
||||
#ifdef REGIONDEBUG
|
||||
printf("Distcheck: %f < %f\n", absDistance, absSplitDist);
|
||||
#endif
|
||||
if (absDistance < absSplitDist &&
|
||||
(current_node->normal[0] == 1.0f || current_node->normal[0] == -1.0f ||
|
||||
(current_node->normal[1] == 1.0f && distance < 0.0f) ||
|
||||
(current_node->normal[1] == -1.0f && distance > 0.0f)))
|
||||
{
|
||||
return RegionTypeWater;
|
||||
}
|
||||
else if (region_node->region_type == ClassWaterOcean2 || checkEdgedAngle)
|
||||
{
|
||||
if (current_node->normal[2] == 1.0f || current_node->normal[2] == -1.0f)
|
||||
return RegionTypeNormal;
|
||||
else if (current_node->normal[1] == 0.0f && (current_node->normal[0] < -0.5f || current_node->normal[0] > 0.5f) &&
|
||||
((abs(absDistance * current_node->normal[0]) / 2.0f) < ((abs(absSplitDist * (1.0f / fraction))))))
|
||||
{
|
||||
return RegionTypeWater;
|
||||
}
|
||||
else if (current_node->normal[1] == 0.0f && (current_node->normal[2] < -0.5f || current_node->normal[2] > 0.5f) &&
|
||||
((abs(absDistance * current_node->normal[2]) / 2.0f) < ((abs(absSplitDist * (1.0f / fraction))))))
|
||||
{
|
||||
return RegionTypeWater;
|
||||
}
|
||||
}
|
||||
|
||||
return RegionTypeNormal;
|
||||
}
|
52
EQ2/source/WorldServer/Zone/region_map_v1.h
Normal file
52
EQ2/source/WorldServer/Zone/region_map_v1.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
#ifndef EQ2EMU_REGION_MAP_V1_H
|
||||
#define EQ2EMU_REGION_MAP_V1_H
|
||||
|
||||
#include "region_map.h"
|
||||
#include <map>
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct ZBSP_Node {
|
||||
int32 node_number;
|
||||
float normal[3], splitdistance;
|
||||
int32 region;
|
||||
int32 special;
|
||||
int32 left, right;
|
||||
} ZBSP_Node;
|
||||
|
||||
typedef struct Region_Node {
|
||||
int32 region_type;
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float dist;
|
||||
} Region_Node;
|
||||
#pragma pack()
|
||||
|
||||
class RegionMapV1 : public RegionMap
|
||||
{
|
||||
public:
|
||||
RegionMapV1();
|
||||
~RegionMapV1();
|
||||
|
||||
virtual WaterRegionType ReturnRegionType(const glm::vec3& location, float belowY = -999999.0f) const;
|
||||
virtual bool InWater(const glm::vec3& location, float belowY = -999999.0f) const;
|
||||
virtual bool InLava(const glm::vec3& location) const;
|
||||
virtual bool InLiquid(const glm::vec3& location) const;
|
||||
virtual bool InPvP(const glm::vec3& location) const;
|
||||
virtual bool InZoneLine(const glm::vec3& location) const;
|
||||
|
||||
protected:
|
||||
virtual bool Load(FILE *fp);
|
||||
|
||||
private:
|
||||
WaterRegionType BSPReturnRegionType(int32 node_number, const glm::vec3& location) const;
|
||||
WaterRegionType BSPReturnRegionTypeNode(const Region_Node* node, const ZBSP_Node* BSP_Root, int32 node_number, const glm::vec3& location, float distToNode=0.0f) const;
|
||||
|
||||
WaterRegionType BSPReturnRegionWaterRegion(const Region_Node* node, const ZBSP_Node* BSP_Root, int32 node_number, const glm::vec3& location, float distToNode=0.0f) const;
|
||||
map<Region_Node*, ZBSP_Node*> Regions;
|
||||
|
||||
WaterRegionType EstablishDistanceAtAngle(const Region_Node* region_node, const ZBSP_Node* current_node, float distance, float absDistance, float absSplitDist, bool checkEdgedAngle=false) const;
|
||||
friend class RegionMap;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,26 +0,0 @@
|
|||
|
||||
|
||||
#include "water_map.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fstream>
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
inline bool file_exists(const std::string& name) {
|
||||
std::ifstream f(name.c_str());
|
||||
return f.good();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param zone_name
|
||||
* @return
|
||||
*/
|
||||
WaterMap* WaterMap::LoadWaterMapfile(std::string zone_name) {
|
||||
return nullptr;
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
#ifndef EQEMU_WATER_MAP_H
|
||||
#define EQEMU_WATER_MAP_H
|
||||
|
||||
#include "../../common/types.h"
|
||||
#include "position.h"
|
||||
#include <string>
|
||||
|
||||
enum WaterRegionType : int {
|
||||
RegionTypeUnsupported = -2,
|
||||
RegionTypeUntagged = -1,
|
||||
RegionTypeNormal = 0,
|
||||
RegionTypeWater = 1,
|
||||
RegionTypeLava = 2,
|
||||
RegionTypeZoneLine = 3,
|
||||
RegionTypePVP = 4,
|
||||
RegionTypeSlime = 5,
|
||||
RegionTypeIce = 6,
|
||||
RegionTypeVWater = 7
|
||||
};
|
||||
|
||||
class WaterMap
|
||||
{
|
||||
public:
|
||||
WaterMap() { }
|
||||
virtual ~WaterMap() { }
|
||||
|
||||
static WaterMap* LoadWaterMapfile(std::string zone_name);
|
||||
virtual WaterRegionType ReturnRegionType(const glm::vec3& location) const = 0;
|
||||
virtual bool InWater(const glm::vec3& location) const = 0;
|
||||
virtual bool InVWater(const glm::vec3& location) const = 0;
|
||||
virtual bool InLava(const glm::vec3& location) const = 0;
|
||||
virtual bool InLiquid(const glm::vec3& location) const = 0;
|
||||
virtual bool InPvP(const glm::vec3& location) const = 0;
|
||||
virtual bool InZoneLine(const glm::vec3& location) const = 0;
|
||||
|
||||
protected:
|
||||
virtual bool Load(FILE *fp) { return false; }
|
||||
};
|
||||
|
||||
#endif
|
|
@ -158,6 +158,7 @@ ZoneServer::ZoneServer(const char* name) {
|
|||
Grid = nullptr;
|
||||
zonemap = nullptr;
|
||||
pathing = nullptr;
|
||||
regionmap = nullptr;
|
||||
strcpy(zonesky_file,"");
|
||||
|
||||
reloading = true;
|
||||
|
@ -215,6 +216,8 @@ ZoneServer::~ZoneServer() {
|
|||
if (movementMgr != nullptr)
|
||||
delete movementMgr;
|
||||
|
||||
if (regionmap != nullptr)
|
||||
delete regionmap;
|
||||
LogWrite(ZONE__INFO, 0, "Zone", "Completed zone shutdown of '%s'", zone_name);
|
||||
--numzones;
|
||||
UpdateWindowTitle(0);
|
||||
|
@ -282,6 +285,10 @@ void ZoneServer::Init()
|
|||
if (zonemap == nullptr) {
|
||||
zonemap = Map::LoadMapFile(zoneName, Grid);
|
||||
}
|
||||
if (regionmap == nullptr) {
|
||||
regionmap = RegionMap::LoadRegionMapfile(zoneName);
|
||||
}
|
||||
|
||||
pathing = IPathfinder::Load(zoneName);
|
||||
movementMgr = new MobMovementManager();
|
||||
// else
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "Zone/map.h"
|
||||
#include "Zone/pathfinder_interface.h"
|
||||
#include "Zone/mob_movement_manager.h"
|
||||
#include "Zone/region_map.h"
|
||||
|
||||
extern NetConnection net; // needs to be here or compile errors in commands.cpp
|
||||
class SpellProcess;
|
||||
|
@ -444,6 +445,7 @@ public:
|
|||
|
||||
SPGrid* Grid;
|
||||
Map* zonemap;
|
||||
RegionMap* regionmap;
|
||||
IPathfinder* pathing;
|
||||
MobMovementManager* movementMgr;
|
||||
|
||||
|
|
|
@ -499,6 +499,19 @@ LOG_TYPE(MAP, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLE
|
|||
LOG_TYPE(MAP, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
|
||||
LOG_TYPE(MAP, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
|
||||
LOG_TYPE(MAP, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
|
||||
LOG_TYPE(MAP, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
|
||||
LOG_TYPE(MAP, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
|
||||
|
||||
|
||||
/*** Region Map Loggers ********************************************************************************/
|
||||
// RegionMap-related events, status, messaging, access
|
||||
LOG_CATEGORY(REGION)
|
||||
LOG_TYPE(REGION, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
|
||||
LOG_TYPE(REGION, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
|
||||
LOG_TYPE(REGION, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
|
||||
LOG_TYPE(REGION, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
|
||||
LOG_TYPE(REGION, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
|
||||
LOG_TYPE(REGION, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
|
||||
|
||||
#undef LOG_TYPE
|
||||
#undef LOG_CATEGORY
|
||||
|
|
|
@ -38,9 +38,9 @@
|
|||
#endif
|
||||
|
||||
#if defined(LOGIN)
|
||||
#define CURRENT_VERSION "0.8.1-libra1"
|
||||
#define CURRENT_VERSION "0.9.0-libra2"
|
||||
#elif defined(WORLD)
|
||||
#define CURRENT_VERSION "0.8.1-libra1"
|
||||
#define CURRENT_VERSION "0.9.0-libra2"
|
||||
#else
|
||||
#define CURRENT_VERSION "0.7.3-dev"
|
||||
#endif
|
||||
|
|
|
@ -355,8 +355,9 @@
|
|||
<ClCompile Include="..\..\source\WorldServer\Zone\pathfinder_waypoint.cpp" />
|
||||
<ClCompile Include="..\..\source\WorldServer\Zone\position.cpp" />
|
||||
<ClCompile Include="..\..\source\WorldServer\Zone\raycast_mesh.cpp" />
|
||||
<ClCompile Include="..\..\source\WorldServer\Zone\region_map.cpp" />
|
||||
<ClCompile Include="..\..\source\WorldServer\Zone\region_map_v1.cpp" />
|
||||
<ClCompile Include="..\..\source\WorldServer\Zone\SPGrid.cpp" />
|
||||
<ClCompile Include="..\..\source\WorldServer\Zone\water_map.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\source\common\DatabaseNew.h" />
|
||||
|
@ -500,8 +501,9 @@
|
|||
<ClInclude Include="..\..\source\WorldServer\Zone\pathfinder_waypoint.h" />
|
||||
<ClInclude Include="..\..\source\WorldServer\Zone\position.h" />
|
||||
<ClInclude Include="..\..\source\WorldServer\Zone\raycast_mesh.h" />
|
||||
<ClInclude Include="..\..\source\WorldServer\Zone\region_map.h" />
|
||||
<ClInclude Include="..\..\source\WorldServer\Zone\region_map_v1.h" />
|
||||
<ClInclude Include="..\..\source\WorldServer\Zone\SPGrid.h" />
|
||||
<ClInclude Include="..\..\source\WorldServer\Zone\water_map.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
|
|
@ -559,9 +559,6 @@
|
|||
<ClCompile Include="..\..\source\WorldServer\Zone\mob_movement_manager.cpp">
|
||||
<Filter>Source Files\Zone</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\WorldServer\Zone\water_map.cpp">
|
||||
<Filter>Source Files\Zone</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\WorldServer\Zone\pathfinder_interface.cpp">
|
||||
<Filter>Source Files\Zone</Filter>
|
||||
</ClCompile>
|
||||
|
@ -577,6 +574,12 @@
|
|||
<ClCompile Include="..\..\source\WorldServer\Zone\pathfinder_waypoint.cpp">
|
||||
<Filter>Source Files\Zone</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\WorldServer\Zone\region_map.cpp">
|
||||
<Filter>Source Files\Zone</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\WorldServer\Zone\region_map_v1.cpp">
|
||||
<Filter>Source Files\Zone</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\source\common\Common_Defines.h">
|
||||
|
@ -993,9 +996,6 @@
|
|||
<ClInclude Include="..\..\source\WorldServer\Zone\mob_movement_manager.h">
|
||||
<Filter>Header Files\Zone</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\source\WorldServer\Zone\water_map.h">
|
||||
<Filter>Header Files\Zone</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\source\WorldServer\Zone\pathfinder_interface.h">
|
||||
<Filter>Header Files\Zone</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1008,5 +1008,11 @@
|
|||
<ClInclude Include="..\..\source\WorldServer\Zone\pathfinder_waypoint.h">
|
||||
<Filter>Header Files\Zone</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\source\WorldServer\Zone\region_map.h">
|
||||
<Filter>Header Files\Zone</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\source\WorldServer\Zone\region_map_v1.h">
|
||||
<Filter>Header Files\Zone</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -352,4 +352,12 @@
|
|||
<ConfigType Type="PACKET" Level="9" Color="Yellow" Enabled="False" Logs="3" />
|
||||
<ConfigType Type="TRACE" Level="9" Color="Yellow" Enabled="False" Logs="1" />
|
||||
</LogConfig>
|
||||
<LogConfig Category="REGION">
|
||||
<ConfigType Type="INFO" Level="9" Color="WhiteBold" Enabled="True" Logs="3" />
|
||||
<ConfigType Type="WARNING" Level="9" Color="YellowBold" Enabled="True" Logs="3" />
|
||||
<ConfigType Type="ERROR" Level="9" Color="RedBold" Enabled="True" Logs="3" />
|
||||
<ConfigType Type="DEBUG" Level="9" Color="GreenBold" Enabled="False" Logs="3" />
|
||||
<ConfigType Type="PACKET" Level="9" Color="Yellow" Enabled="False" Logs="3" />
|
||||
<ConfigType Type="TRACE" Level="9" Color="Yellow" Enabled="False" Logs="1" />
|
||||
</LogConfig>
|
||||
</EQ2EmuLogConfigs>
|
||||
|
|
Loading…
Reference in a new issue