Player/Target Radius added to distance checks
Radius is now built into the GetDistance formula, it also is based on f32/32.0f per recommendations of peak (Thx peak!) Added combat range as a rule: rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat() Fixes #53
This commit is contained in:
parent
442868f80a
commit
04498a2490
11 changed files with 113 additions and 47 deletions
|
@ -2,6 +2,9 @@
|
|||
#include "../Combat.h"
|
||||
#include "../Spells.h"
|
||||
#include "../../common/Log.h"
|
||||
#include "../Rules/Rules.h"
|
||||
|
||||
extern RuleManager rule_manager;
|
||||
|
||||
BotBrain::BotBrain(Bot* body) : Brain(body) {
|
||||
Body = body;
|
||||
|
@ -46,11 +49,9 @@ void BotBrain::Think() {
|
|||
|
||||
// Get distance from the owner
|
||||
float distance = GetBody()->GetDistance(target);
|
||||
distance -= target->appearance.pos.collision_radius / 10;
|
||||
distance -= GetBody()->appearance.pos.collision_radius / 10;
|
||||
|
||||
// If out of melee range then move closer
|
||||
if (distance > MAX_COMBAT_RANGE)
|
||||
if (distance > rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat())
|
||||
MoveCloser(target);
|
||||
}
|
||||
|
||||
|
|
|
@ -170,7 +170,7 @@ bool Entity::AttackAllowed(Entity* target, float distance, bool range_attack) {
|
|||
}
|
||||
}
|
||||
else if (distance != 0) {
|
||||
if(distance >= MAX_COMBAT_RANGE) {
|
||||
if(distance >= rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat()) {
|
||||
LogWrite(COMBAT__DEBUG, 3, "AttackAllowed", "Failed to attack: distance is beyond melee range");
|
||||
return false;
|
||||
}
|
||||
|
@ -1151,8 +1151,6 @@ void Player::ProcessCombat() {
|
|||
|
||||
float distance = 0;
|
||||
distance = GetDistance(combat_target);
|
||||
distance -= combat_target->appearance.pos.collision_radius / 10;
|
||||
distance -= appearance.pos.collision_radius / 10;
|
||||
|
||||
// Check to see if we are doing ranged auto attacks if not check to see if we are in melee range
|
||||
if (GetRangeAttack()) {
|
||||
|
@ -1185,7 +1183,7 @@ void Player::ProcessCombat() {
|
|||
}
|
||||
}
|
||||
}
|
||||
else if(distance <= MAX_COMBAT_RANGE) {
|
||||
else if(distance <= rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat()) {
|
||||
// We are doing melee auto attacks and are within range
|
||||
|
||||
// Check to see if we can attack the target
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
#define COMBAT_NORMAL_FIGHTER 0
|
||||
#define COMBAT_ADD_FIGHTER 1
|
||||
#define COMBAT_REMOVE_FIGHTER 2
|
||||
#define MAX_COMBAT_RANGE 3
|
||||
// replace with rule rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat()
|
||||
//#define MAX_COMBAT_RANGE 3
|
||||
|
||||
class ZoneServer;
|
||||
class SpellProcess;
|
||||
|
|
|
@ -864,8 +864,6 @@ int EQ2Emu_lua_SpellHeal(lua_State* state) {
|
|||
luaspell->resisted = false;
|
||||
if (target) {
|
||||
float distance = caster->GetDistance(target, true);
|
||||
distance -= caster->appearance.pos.collision_radius / 10;
|
||||
distance -= target->appearance.pos.collision_radius / 10;
|
||||
if (((Entity*)caster)->SpellHeal(target, distance, luaspell, heal_type, min_heal, max_heal, crit_mod, no_calcs))
|
||||
success = true;
|
||||
}
|
||||
|
@ -876,8 +874,6 @@ int EQ2Emu_lua_SpellHeal(lua_State* state) {
|
|||
for (int32 i = 0; i < luaspell->targets.size(); i++) {
|
||||
if ((target = zone->GetSpawnByID(luaspell->targets[i]))) {
|
||||
float distance = caster->GetDistance(target, true);
|
||||
distance -= caster->appearance.pos.collision_radius / 10;
|
||||
distance -= target->appearance.pos.collision_radius / 10;
|
||||
((Entity*)caster)->SpellHeal(target, distance, luaspell, heal_type, min_heal, max_heal, crit_mod, no_calcs);
|
||||
}
|
||||
}
|
||||
|
@ -1230,8 +1226,6 @@ int EQ2Emu_lua_SpellDamage(lua_State* state) {
|
|||
race_match = true; // if the race_req.size = 0 then there is no race requirement and the race_match will be true
|
||||
if (race_match == true) {
|
||||
float distance = caster->GetDistance(target, true);
|
||||
distance -= caster->appearance.pos.collision_radius / 10;
|
||||
distance -= target->appearance.pos.collision_radius / 10;
|
||||
((Entity*)caster)->SpellAttack(target, distance, luaspell, type, min_damage, max_damage, crit_mod, no_calcs);
|
||||
}
|
||||
}
|
||||
|
@ -1253,8 +1247,6 @@ int EQ2Emu_lua_SpellDamage(lua_State* state) {
|
|||
race_match = true; // if the race_req.size = 0 then there is no race requirement and the race_match will be true
|
||||
if (race_match == true) {
|
||||
float distance = caster->GetDistance(target, true);
|
||||
distance -= caster->appearance.pos.collision_radius / 10;
|
||||
distance -= target->appearance.pos.collision_radius / 10;
|
||||
if (((Entity*)caster)->SpellAttack(target, distance, luaspell, type, min_damage, max_damage, crit_mod, no_calcs))
|
||||
success = true;
|
||||
}
|
||||
|
@ -2322,11 +2314,7 @@ int EQ2Emu_lua_GetDistance(lua_State* state) {
|
|||
Spawn* spawn2 = lua_interface->GetSpawn(state, 2);
|
||||
bool include_radius = lua_interface->GetInt8Value(state, 3) == 1;
|
||||
if (spawn && spawn2) {
|
||||
float distance = spawn->GetDistance(spawn2);
|
||||
if (include_radius) {
|
||||
distance -= spawn->appearance.pos.collision_radius / 10;
|
||||
distance -= spawn2->appearance.pos.collision_radius / 10;
|
||||
}
|
||||
float distance = spawn->GetDistance(spawn2, false, include_radius);
|
||||
|
||||
lua_interface->SetFloatValue(state, distance);
|
||||
return 1;
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
#include "../common/Log.h"
|
||||
#include "LuaInterface.h"
|
||||
#include "World.h"
|
||||
#include "Rules/Rules.h"
|
||||
|
||||
extern RuleManager rule_manager;
|
||||
|
||||
extern LuaInterface* lua_interface;
|
||||
extern World world;
|
||||
|
@ -101,8 +104,6 @@ void Brain::Think() {
|
|||
// Still within max chase distance lets to the combat stuff now
|
||||
|
||||
float distance = m_body->GetDistance(target);
|
||||
distance -= target->appearance.pos.collision_radius / 10;
|
||||
distance -= m_body->appearance.pos.collision_radius / 10;
|
||||
|
||||
if(!m_body->IsCasting() && (!HasRecovered() || !ProcessSpell(target, distance))) {
|
||||
LogWrite(NPC_AI__DEBUG, 7, "NPC_AI", "%s is attempting melee on %s.", m_body->GetName(), target->GetName());
|
||||
|
@ -328,7 +329,7 @@ bool Brain::CheckBuffs() {
|
|||
}
|
||||
|
||||
void Brain::ProcessMelee(Entity* target, float distance) {
|
||||
if(distance > MAX_COMBAT_RANGE)
|
||||
if(distance > rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat())
|
||||
MoveCloser(target);
|
||||
else {
|
||||
if (target) {
|
||||
|
@ -479,11 +480,9 @@ void CombatPetBrain::Think() {
|
|||
|
||||
// Get distance from the owner
|
||||
float distance = GetBody()->GetDistance(target);
|
||||
distance -= target->appearance.pos.collision_radius / 10;
|
||||
distance -= GetBody()->appearance.pos.collision_radius / 10;
|
||||
|
||||
// If out of melee range then move closer
|
||||
if (distance > MAX_COMBAT_RANGE)
|
||||
if (distance > rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat())
|
||||
MoveCloser(target);
|
||||
}
|
||||
|
||||
|
@ -513,11 +512,9 @@ void NonCombatPetBrain::Think() {
|
|||
|
||||
// Get distance from the owner
|
||||
float distance = GetBody()->GetDistance(target);
|
||||
distance -= target->appearance.pos.collision_radius / 10;
|
||||
distance -= GetBody()->appearance.pos.collision_radius / 10;
|
||||
|
||||
// If out of melee range then move closer
|
||||
if (distance > MAX_COMBAT_RANGE)
|
||||
if (distance > rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat())
|
||||
MoveCloser(target);
|
||||
}
|
||||
|
||||
|
@ -591,8 +588,6 @@ void DumbFirePetBrain::Think() {
|
|||
}
|
||||
|
||||
float distance = GetBody()->GetDistance(target);
|
||||
distance -= target->appearance.pos.collision_radius / 10;
|
||||
distance -= GetBody()->appearance.pos.collision_radius / 10;
|
||||
|
||||
if(!GetBody()->IsCasting() && (!HasRecovered() || !ProcessSpell(target, distance))) {
|
||||
LogWrite(NPC_AI__DEBUG, 7, "NPC_AI", "%s is attempting melee on %s.", GetBody()->GetName(), target->GetName());
|
||||
|
|
|
@ -207,6 +207,8 @@ RuleManager::RuleManager() {
|
|||
RULE_INIT(R_PVP, LevelRange, "4");
|
||||
RULE_INIT(R_PVP, InvisPlayerDiscoveryRange, "20"); // value > 0 sets radius inner to see, = 0 means always seen, -1 = never seen
|
||||
|
||||
/* COMBAT */
|
||||
RULE_INIT(R_Combat, MaxCombatRange, "4.0");
|
||||
/* SPAWN */
|
||||
RULE_INIT(R_Spawn, SpeedMultiplier, "300"); // note: this value was 1280 until 6/1/2009, then was 600 til Sep 2009, when it became 300...?
|
||||
RULE_INIT(R_Spawn, SpeedRatio, "0"); // was 1280/7.5 and 600/7.5 until it became 300.
|
||||
|
|
|
@ -33,6 +33,7 @@ enum RuleCategory {
|
|||
R_Guild,
|
||||
R_Player,
|
||||
R_PVP,
|
||||
R_Combat,
|
||||
R_Spawn,
|
||||
R_UI,
|
||||
R_World,
|
||||
|
@ -74,6 +75,9 @@ enum RuleType {
|
|||
LevelRange,
|
||||
InvisPlayerDiscoveryRange,
|
||||
|
||||
/* COMBAT */
|
||||
MaxCombatRange,
|
||||
|
||||
/* SPAWN */
|
||||
SpeedMultiplier,
|
||||
SpeedRatio,
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "../common/timer.h"
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <emmintrin.h>
|
||||
#include "Entity.h"
|
||||
#include "Widget.h"
|
||||
#include "Sign.h"
|
||||
|
@ -1078,20 +1079,64 @@ float Spawn::GetDistance(float x1, float y1, float z1, float x2, float y2, float
|
|||
return sqrt(x1*x1 + y1*y1 + z1*z1);
|
||||
}
|
||||
|
||||
float Spawn::GetDistance(float x, float y, float z, bool ignore_y){
|
||||
if(ignore_y)
|
||||
return GetDistance(x, y, z, GetX(), y, GetZ());
|
||||
float Spawn::GetDistance(float x, float y, float z, float radius, bool ignore_y) {
|
||||
if (ignore_y)
|
||||
return GetDistance(x, y, z, GetX(), y, GetZ()) - radius;
|
||||
else
|
||||
return GetDistance(x, y, z, GetX(), GetY(), GetZ());
|
||||
return GetDistance(x, y, z, GetX(), GetY(), GetZ()) - radius;
|
||||
}
|
||||
|
||||
float Spawn::GetDistance(Spawn* spawn, bool ignore_y){
|
||||
float Spawn::GetDistance(float x, float y, float z, bool ignore_y) {
|
||||
return GetDistance(x, y, z, 0.0f, ignore_y);
|
||||
}
|
||||
float Spawn::GetDistance(Spawn* spawn, bool ignore_y, bool includeRadius){
|
||||
float ret = 0;
|
||||
if(spawn)
|
||||
ret = GetDistance(spawn->GetX(), spawn->GetY(), spawn->GetZ(), ignore_y);
|
||||
|
||||
if (spawn)
|
||||
{
|
||||
float radius = 0.0f;
|
||||
if (includeRadius)
|
||||
radius = CalculateRadius(spawn);
|
||||
ret = GetDistance(spawn->GetX(), spawn->GetY(), spawn->GetZ(), radius, ignore_y);
|
||||
}
|
||||
|
||||
// maybe distance against ourselves, in that case we want to nullify the radius check
|
||||
if (ret < 0)
|
||||
ret = 0.0f;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
float Spawn::GetDistance(Spawn* spawn, float x1, float y1, float z1, bool includeRadius) {
|
||||
float ret = 0;
|
||||
|
||||
if (spawn)
|
||||
{
|
||||
float radius = 0.0f;
|
||||
if (includeRadius)
|
||||
radius = CalculateRadius(spawn);
|
||||
ret = GetDistance(x1, y1, z1, spawn->GetX(), spawn->GetY(), spawn->GetZ()) - radius;
|
||||
}
|
||||
|
||||
// maybe distance against ourselves, in that case we want to nullify the radius check
|
||||
if (ret < 0)
|
||||
ret = 0.0f;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
float Spawn::CalculateRadius(Spawn* target)
|
||||
{
|
||||
float srcRadius = short_to_float(appearance.pos.collision_radius);
|
||||
if (target)
|
||||
{
|
||||
float targRadius = short_to_float(target->appearance.pos.collision_radius);
|
||||
return (targRadius / 32.0f) + (srcRadius / 32.0f);
|
||||
}
|
||||
else
|
||||
return (srcRadius / 32.0f);
|
||||
}
|
||||
|
||||
int32 Spawn::GetRespawnTime(){
|
||||
return respawn;
|
||||
}
|
||||
|
@ -1841,19 +1886,19 @@ void Spawn::ProcessMovement(bool isSpawnListLocked){
|
|||
SetSpeed(speed);
|
||||
}
|
||||
MovementLocation* loc = GetCurrentRunningLocation();
|
||||
if (GetDistance(followTarget, true) <= MAX_COMBAT_RANGE || (loc && loc->x == GetX() && loc->y == GetY() && loc->z == GetZ())) {
|
||||
if ((GetDistance(followTarget, true) <= rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat()) || (loc && loc->x == GetX() && loc->y == GetY() && loc->z == GetZ())) {
|
||||
ClearRunningLocations();
|
||||
CalculateRunningLocation(true);
|
||||
}
|
||||
else if (loc) {
|
||||
float distance = GetDistance(loc->x, loc->y, loc->z, followTarget->GetX(), followTarget->GetY(), followTarget->GetZ());
|
||||
if (distance > MAX_COMBAT_RANGE) {
|
||||
MoveToLocation(followTarget, MAX_COMBAT_RANGE);
|
||||
float distance = GetDistance(followTarget, loc->x, loc->y, loc->z);
|
||||
if (distance > rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat()) {
|
||||
MoveToLocation(followTarget, rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat());
|
||||
CalculateRunningLocation();
|
||||
}
|
||||
}
|
||||
else {
|
||||
MoveToLocation(followTarget, MAX_COMBAT_RANGE);
|
||||
MoveToLocation(followTarget, rule_manager.GetGlobalRule(R_Combat, MaxCombatRange)->GetFloat());
|
||||
CalculateRunningLocation();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -590,9 +590,13 @@ public:
|
|||
int32 GetID(){
|
||||
return id;
|
||||
}
|
||||
float GetDistance(Spawn* spawn, bool ignore_y = false);
|
||||
float GetDistance(float x, float y, float z, bool ignore_y = false);
|
||||
float GetDistance(float x1, float y1, float z1, float x2, float y2, float z2);
|
||||
float GetDistance(float x, float y, float z, float radius, bool ignore_y = false);
|
||||
float GetDistance(float x, float y, float z, bool ignore_y = false);
|
||||
float GetDistance(Spawn* spawn, bool ignore_y = false, bool includeRadius=true);
|
||||
float GetDistance(Spawn* spawn, float x1, float y1, float z1, bool includeRadius=true);
|
||||
float CalculateRadius(Spawn* target);
|
||||
|
||||
int8 GetEncounterLevel(){
|
||||
return appearance.encounter_level;
|
||||
}
|
||||
|
|
|
@ -922,4 +922,27 @@ strlcpy(char *dst, const char *src, size_t size) {
|
|||
}
|
||||
|
||||
return(s - src - 1);
|
||||
}
|
||||
}
|
||||
|
||||
float short_to_float(const ushort x) { // IEEE-754 16-bit floating-point format (without infinity): 1-5-10, exp-15, +-131008.0, +-6.1035156E-5, +-5.9604645E-8, 3.311 digits
|
||||
const uint32 e = (x & 0x7C00) >> 10; // exponent
|
||||
const uint32 m = (x & 0x03FF) << 13; // mantissa
|
||||
const uint32 v = as_uint((float)m) >> 23; // evil log2 bit hack to count leading zeros in denormalized format
|
||||
return as_float((x & 0x8000) << 16 | (e != 0) * ((e + 112) << 23 | m) | ((e == 0) & (m != 0)) * ((v - 37) << 23 | ((m << (150 - v)) & 0x007FE000))); // sign : normalized : denormalized
|
||||
}
|
||||
|
||||
uint32 float_to_int(const float x) { // IEEE-754 16-bit floating-point format (without infinity): 1-5-10, exp-15, +-131008.0, +-6.1035156E-5, +-5.9604645E-8, 3.311 digits
|
||||
const uint32 b = as_uint(x) + 0x00001000; // round-to-nearest-even: add last bit after truncated mantissa
|
||||
const uint32 e = (b & 0x7F800000) >> 23; // exponent
|
||||
const uint32 m = b & 0x007FFFFF; // mantissa; in line below: 0x007FF000 = 0x00800000-0x00001000 = decimal indicator flag - initial rounding
|
||||
return (b & 0x80000000) >> 16 | (e > 112)* ((((e - 112) << 10) & 0x7C00) | m >> 13) | ((e < 113) & (e > 101))* ((((0x007FF000 + m) >> (125 - e)) + 1) >> 1) | (e > 143) * 0x7FFF; // sign : normalized : denormalized : saturate
|
||||
}
|
||||
|
||||
uint32 as_uint(const float x) {
|
||||
return *(uint32*)&x;
|
||||
}
|
||||
|
||||
float as_float(const uint32 x) {
|
||||
return *(float*)&x;
|
||||
}
|
||||
|
||||
|
|
|
@ -80,6 +80,11 @@ int16 GetOpcodeVersion(int16 version);
|
|||
void SleepMS(int32 milliseconds);
|
||||
size_t strlcpy(char *dst, const char *src, size_t size);
|
||||
|
||||
float short_to_float(const ushort x);
|
||||
uint32 float_to_int(const float x);
|
||||
uint32 as_uint(const float x);
|
||||
float as_float(const uint32 x);
|
||||
|
||||
bool INIReadBool(FILE *f, const char *section, const char *property, bool *out);
|
||||
bool INIReadInt(FILE *f, const char *section, const char *property, int *out);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue