1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
#include <cassert>
#include "MoveType.h"
#include "Map/Ground.h"
#include "Sim/Misc/QuadField.h"
#include "Sim/Units/Unit.h"
#include "Sim/Units/UnitDef.h"
#include "System/myMath.h"
#include "System/Sync/HsiehHash.h"
CR_BIND_DERIVED_INTERFACE(AMoveType, CObject)
CR_REG_METADATA(AMoveType, (
CR_MEMBER(owner),
CR_MEMBER(goalPos),
CR_MEMBER(oldPos),
CR_MEMBER(oldSlowUpdatePos),
CR_MEMBER(maxSpeed),
CR_MEMBER(maxSpeedDef),
CR_MEMBER(maxWantedSpeed),
CR_MEMBER(maneuverLeash),
CR_MEMBER(useHeading),
CR_MEMBER(progressState)
))
AMoveType::AMoveType(CUnit* owner):
owner(owner),
goalPos(owner? owner->pos: ZeroVector),
oldPos(owner? owner->pos: ZeroVector),
oldSlowUpdatePos(oldPos),
useHeading(true),
progressState(Done),
maxSpeed(owner? owner->unitDef->speed / GAME_SPEED : 0.0f),
maxSpeedDef(owner? owner->unitDef->speed / GAME_SPEED : 0.0f),
maxWantedSpeed(owner? owner->unitDef->speed / GAME_SPEED : 0.0f),
maneuverLeash(500.0f)
{
}
void AMoveType::SlowUpdate()
{
if (owner->pos != oldSlowUpdatePos) {
oldSlowUpdatePos = owner->pos;
const int newMapSquare = CGround::GetSquare(owner->pos);
if (newMapSquare != owner->mapSquare) {
owner->mapSquare = newMapSquare;
if (!owner->UsingScriptMoveType()) {
if ((owner->IsOnGround() || owner->IsInWater()) && owner->unitDef->IsGroundUnit()) {
// always (re-)add us to occupation map if we moved
// (since our last SlowUpdate) and are on the ground
// NOTE: ships are ground units but not on the ground
owner->Block();
}
}
}
quadField->MovedUnit(owner);
}
}
void AMoveType::KeepPointingTo(CUnit* unit, float distance, bool aggressive)
{
KeepPointingTo(float3(unit->pos), distance, aggressive);
}
float AMoveType::CalcStaticTurnRadius() const {
// calculate a rough turn radius (not based on current speed)
const float turnFrames = SPRING_CIRCLE_DIVS / std::max(owner->unitDef->turnRate, 1.0f);
const float turnRadius = (maxSpeedDef * turnFrames) / (PI + PI);
return turnRadius;
}
bool AMoveType::SetMemberValue(unsigned int memberHash, void* memberValue) {
#define MEMBER_CHARPTR_HASH(memberName) HsiehHash(memberName, strlen(memberName), 0)
#define MEMBER_LITERAL_HASH(memberName) HsiehHash(memberName, sizeof(memberName) - 1, 0)
#define MAXSPEED_MEMBER_IDX 0
#define MAXWANTEDSPEED_MEMBER_IDX 1
#define MANEUVERLEASH_MEMBER_IDX 2
static const unsigned int floatMemberHashes[] = {
MEMBER_LITERAL_HASH( "maxSpeed"),
MEMBER_LITERAL_HASH( "maxWantedSpeed"),
MEMBER_LITERAL_HASH( "maneuverLeash"),
};
#undef MEMBER_CHARPTR_HASH
#undef MEMBER_LITERAL_HASH
/*
// unordered_map etc. perform dynallocs, so KISS here
float* floatMemberPtrs[] = {
&maxSpeed,
&maxWantedSpeed,
};
*/
// special cases
if (memberHash == floatMemberHashes[MAXSPEED_MEMBER_IDX]) {
SetMaxSpeed((*reinterpret_cast<float*>(memberValue)) / GAME_SPEED);
return true;
}
if (memberHash == floatMemberHashes[MAXWANTEDSPEED_MEMBER_IDX]) {
SetWantedMaxSpeed((*reinterpret_cast<float*>(memberValue)) / GAME_SPEED);
return true;
}
if (memberHash == floatMemberHashes[MANEUVERLEASH_MEMBER_IDX]) {
SetManeuverLeash(*reinterpret_cast<float*>(memberValue));
return true;
}
return false;
}
|