forked from oerkki/voxelands
start mob sao code
This commit is contained in:
parent
bf49ed590b
commit
0c892736e7
|
@ -108,7 +108,7 @@ void content_mob_init()
|
|||
f->level = MOB_DESTRUCTIVE;
|
||||
f->setTexture("mob_fireball.png");
|
||||
f->punch_action = MPA_IGNORE;
|
||||
f->motion = MM_THROWN;
|
||||
f->motion = MM_CONSTANT;
|
||||
f->motion_type = MMT_FLY;
|
||||
f->glow_light = LIGHT_MAX-1;
|
||||
f->setCollisionBox(aabb3f(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.));
|
||||
|
|
|
@ -44,7 +44,8 @@ enum MobMotion
|
|||
MM_WANDER,
|
||||
MM_SEEKER,
|
||||
MM_SENTRY,
|
||||
MM_THROWN
|
||||
MM_THROWN,
|
||||
MM_CONSTANT
|
||||
};
|
||||
|
||||
enum MobMotionType
|
||||
|
@ -87,13 +88,17 @@ struct MobFeatures {
|
|||
MobMotionType motion_type;
|
||||
MobState spawn_state;
|
||||
bool is_tamable;
|
||||
bool notices_player;
|
||||
content_t tamed_mob;
|
||||
content_t attack_throw_object;
|
||||
v3f attack_throw_offset;
|
||||
u8 attack_player_damage;
|
||||
u8 glow_light;
|
||||
u8 attack_glow_light;
|
||||
u16 hp;
|
||||
std::string dropped_item;
|
||||
f32 lifetime;
|
||||
u16 contact_explosion_diameter;
|
||||
|
||||
MobFeatures()
|
||||
{
|
||||
|
@ -130,7 +135,22 @@ struct MobFeatures {
|
|||
return collisionbox;
|
||||
if (!nodeboxes.size())
|
||||
return aabb3f(-0.5,-0.5,-0.5,0.5,0.5,0.5);
|
||||
return nodeboxes[0];
|
||||
aabb3f b = nodeboxes[0];
|
||||
b.MinEdge /= BS;
|
||||
b.MaxEdge /= BS;
|
||||
return b;
|
||||
}
|
||||
|
||||
v3f getSize()
|
||||
{
|
||||
aabb3f c = getCollisionBox();
|
||||
return v3f(c.MaxEdge.X-c.MinEdge.X,c.MaxEdge.Y-c.MinEdge.Y,c.MaxEdge.Z-c.MinEdge.Z);
|
||||
}
|
||||
|
||||
v3s16 getSizeBlocks()
|
||||
{
|
||||
v3f s = getSize();
|
||||
return v3s16(s.X+0.5,s.Y+0.5,s.Z+0.5);
|
||||
}
|
||||
|
||||
#ifdef SERVER
|
||||
|
@ -162,12 +182,17 @@ struct MobFeatures {
|
|||
motion_type = MMT_WALK;
|
||||
spawn_state = MS_WILD;
|
||||
is_tamable = false;
|
||||
notices_player = false;
|
||||
tamed_mob = CONTENT_IGNORE;
|
||||
attack_throw_object = CONTENT_IGNORE;
|
||||
attack_throw_offset = v3f(0,0,0);
|
||||
attack_player_damage = 0;
|
||||
glow_light = 0;
|
||||
attack_glow_light = 0;
|
||||
hp = 20;
|
||||
dropped_item = "";
|
||||
lifetime = 0.0;
|
||||
contact_explosion_diameter = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -189,6 +214,7 @@ inline std::string mobLevelS(u8 level)
|
|||
return std::string("passive");
|
||||
}
|
||||
|
||||
MobFeatures & content_mob_features(content_t i);
|
||||
void content_mob_init();
|
||||
|
||||
#define CONTENT_MOB_RAT (CONTENT_MOB_MASK | 0x01)
|
||||
|
|
|
@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#define ACTIVEOBJECT_TYPE_OERKKI1 4
|
||||
#define ACTIVEOBJECT_TYPE_FIREFLY 5
|
||||
#define ACTIVEOBJECT_TYPE_MOBV2 6
|
||||
#define ACTIVEOBJECT_TYPE_MOB 7
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1470,3 +1470,406 @@ void MobV2SAO::doDamage(u16 d)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
MobSAO
|
||||
*/
|
||||
|
||||
// Prototype
|
||||
MobSAO proto_MobSAO(NULL, 0, v3f(0,0,0), CONTENT_IGNORE);
|
||||
|
||||
MobSAO::MobSAO(ServerEnvironment *env, u16 id, v3f pos, content_t type):
|
||||
ServerActiveObject(env, id, pos),
|
||||
m_content(type),
|
||||
m_speed(0,0,0),
|
||||
m_last_sent_position(0,0,0),
|
||||
m_oldpos(0,0,0),
|
||||
m_yaw(0),
|
||||
m_touching_ground(false),
|
||||
m_falling(false),
|
||||
m_next_pos_exists(false),
|
||||
m_age(0),
|
||||
m_hp(10),
|
||||
m_disturb_timer(100000),
|
||||
m_random_disturb_timer(0),
|
||||
m_walk_around(false),
|
||||
m_walk_around_timer(0),
|
||||
m_shoot_reload_timer(0),
|
||||
m_shooting(false),
|
||||
m_shooting_timer(0),
|
||||
m_shoot_y(0)
|
||||
{
|
||||
ServerActiveObject::registerType(getType(), create);
|
||||
}
|
||||
MobSAO::MobSAO(ServerEnvironment *env, u16 id, v3f pos, v3f speed, content_t type):
|
||||
ServerActiveObject(env, id, pos),
|
||||
m_content(type),
|
||||
m_speed(speed),
|
||||
m_last_sent_position(0,0,0),
|
||||
m_oldpos(0,0,0),
|
||||
m_yaw(0),
|
||||
m_touching_ground(false),
|
||||
m_falling(false),
|
||||
m_next_pos_exists(false),
|
||||
m_age(0),
|
||||
m_hp(10),
|
||||
m_disturb_timer(100000),
|
||||
m_random_disturb_timer(0),
|
||||
m_walk_around(false),
|
||||
m_walk_around_timer(0),
|
||||
m_shoot_reload_timer(0),
|
||||
m_shooting(false),
|
||||
m_shooting_timer(0),
|
||||
m_shoot_y(0)
|
||||
{
|
||||
ServerActiveObject::registerType(getType(), create);
|
||||
}
|
||||
MobSAO::~MobSAO()
|
||||
{
|
||||
}
|
||||
ServerActiveObject* MobSAO::create(ServerEnvironment *env, u16 id, v3f pos, const std::string &data)
|
||||
{
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
content_t c = readU16(is);
|
||||
c = content_mob_features(c).content;
|
||||
if (c == CONTENT_IGNORE)
|
||||
return NULL;
|
||||
return new MobSAO(env,id,pos,c);
|
||||
}
|
||||
std::string MobSAO::getStaticData()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
std::string MobSAO::getClientInitializationData()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
void MobSAO::step(float dtime, bool send_recommended)
|
||||
{
|
||||
MobFeatures m = content_mob_features(m_content);
|
||||
Player *disturbing_player = NULL;
|
||||
v3f disturbing_player_off = v3f(0,1,0);
|
||||
v3f disturbing_player_norm = v3f(0,1,0);
|
||||
float disturbing_player_distance = 1000000;
|
||||
float disturbing_player_dir = 0;
|
||||
|
||||
m_age += dtime;
|
||||
|
||||
if (m.lifetime >= 0.0 && m_age >= m.lifetime) {
|
||||
m_removed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
m_random_disturb_timer += dtime;
|
||||
if (m.notices_player) {
|
||||
if (m_random_disturb_timer >= 5.0) {
|
||||
m_random_disturb_timer = 0;
|
||||
m_disturbing_player = "";
|
||||
// Check connected players
|
||||
core::list<Player*> players = m_env->getPlayers(true);
|
||||
for (core::list<Player*>::Iterator i = players.begin(); i != players.end(); i++) {
|
||||
Player *player = *i;
|
||||
v3f playerpos = player->getPosition();
|
||||
f32 dist = m_base_position.getDistanceFrom(playerpos);
|
||||
if (dist < BS*16) {
|
||||
if (myrand_range(0,3) == 0) {
|
||||
actionstream<<"Mob id="<<m_id<<" at "
|
||||
<<PP(m_base_position/BS)
|
||||
<<" got randomly disturbed by "
|
||||
<<player->getName()<<std::endl;
|
||||
m_disturbing_player = player->getName();
|
||||
m_disturb_timer = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_disturbing_player != "") {
|
||||
disturbing_player = m_env->getPlayer(m_disturbing_player.c_str());
|
||||
if (disturbing_player ){
|
||||
disturbing_player_off = disturbing_player->getPosition() - m_base_position;
|
||||
disturbing_player_distance = disturbing_player_off.getLength();
|
||||
disturbing_player_norm = disturbing_player_off;
|
||||
disturbing_player_norm.normalize();
|
||||
disturbing_player_dir = 180./PI*atan2(disturbing_player_norm.Z,disturbing_player_norm.X);
|
||||
}
|
||||
}
|
||||
m_disturb_timer += dtime;
|
||||
|
||||
if (!m_falling && m.attack_throw_object != CONTENT_IGNORE) {
|
||||
m_shooting_timer -= dtime;
|
||||
if (m_shooting_timer <= 0.0 && m_shooting) {
|
||||
m_shooting = false;
|
||||
v3f shoot_pos = m.attack_throw_offset * BS;
|
||||
if (0) {
|
||||
v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
|
||||
dir.Y = m_shoot_y;
|
||||
dir.normalize();
|
||||
v3f speed = dir * BS * 10.0;
|
||||
v3f pos = m_base_position + shoot_pos;
|
||||
infostream<<__FUNCTION_NAME<<": Mob id="<<m_id
|
||||
<<" shooting from "<<PP(pos)
|
||||
<<" at speed "<<PP(speed)<<std::endl;
|
||||
ServerActiveObject *obj = new MobSAO(m_env, 0, pos, speed, m.attack_throw_object);
|
||||
m_env->addActiveObject(obj);
|
||||
}
|
||||
}
|
||||
|
||||
m_shoot_reload_timer += dtime;
|
||||
|
||||
float reload_time = 15.0;
|
||||
if (m_disturb_timer <= 15.0)
|
||||
reload_time = 3.0;
|
||||
|
||||
if (
|
||||
!m_shooting
|
||||
&& m_shoot_reload_timer >= reload_time
|
||||
&& !m_next_pos_exists
|
||||
&& m_disturb_timer <= 60.0
|
||||
) {
|
||||
m_shoot_y = 0;
|
||||
if (
|
||||
m_disturb_timer < 60.0
|
||||
&& disturbing_player
|
||||
&& disturbing_player_distance < 16*BS
|
||||
&& fabs(disturbing_player_norm.Y) < 0.8
|
||||
) {
|
||||
m_yaw = disturbing_player_dir;
|
||||
sendPosition();
|
||||
m_shoot_y += disturbing_player_norm.Y;
|
||||
}else{
|
||||
m_shoot_y = 0.01 * myrand_range(-30,10);
|
||||
}
|
||||
m_shoot_reload_timer = 0.0;
|
||||
m_shooting = true;
|
||||
m_shooting_timer = 1.5;
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// command (2 = shooting)
|
||||
writeU8(os, 2);
|
||||
// time
|
||||
writeF1000(os, m_shooting_timer + 0.1);
|
||||
// bright?
|
||||
writeU8(os, true);
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), false, os.str());
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m.motion == MM_WANDER) {
|
||||
stepMotionWander(dtime);
|
||||
}else if (m.motion == MM_SEEKER) {
|
||||
if (disturbing_player) {
|
||||
stepMotionWander(dtime);
|
||||
}else{
|
||||
stepMotionSeeker(dtime);
|
||||
}
|
||||
}else if (m.motion == MM_SENTRY) {
|
||||
stepMotionSentry(dtime);
|
||||
}else if (m.motion == MM_THROWN) {
|
||||
stepMotionThrown(dtime);
|
||||
}else if (m.motion == MM_CONSTANT) {
|
||||
stepMotionConstant(dtime);
|
||||
}
|
||||
|
||||
if (send_recommended == false)
|
||||
return;
|
||||
|
||||
if (m_base_position.getDistanceFrom(m_last_sent_position) > 0.05*BS)
|
||||
sendPosition();
|
||||
}
|
||||
void MobSAO::stepMotionWander(float dtime)
|
||||
{
|
||||
}
|
||||
void MobSAO::stepMotionSeeker(float dtime)
|
||||
{
|
||||
}
|
||||
void MobSAO::stepMotionSentry(float dtime)
|
||||
{
|
||||
}
|
||||
void MobSAO::stepMotionThrown(float dtime)
|
||||
{
|
||||
}
|
||||
void MobSAO::stepMotionConstant(float dtime)
|
||||
{
|
||||
MobFeatures m = content_mob_features(m_content);
|
||||
m_base_position += m_speed * dtime;
|
||||
|
||||
v3s16 pos_i = floatToInt(m_base_position, BS);
|
||||
v3s16 pos_size_off(0,0,0);
|
||||
if (m.getSizeBlocks().X >= 2.5) {
|
||||
pos_size_off.X = -1;
|
||||
pos_size_off.Y = -1;
|
||||
}
|
||||
if (!checkFreePosition(pos_i + pos_size_off)) {
|
||||
if (m.contact_explosion_diameter > 0)
|
||||
explodeSquare(pos_i, v3s16(m.contact_explosion_diameter,m.contact_explosion_diameter,m.contact_explosion_diameter));
|
||||
m_removed = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
bool MobSAO::checkFreePosition(v3s16 p0)
|
||||
{
|
||||
assert(m_env);
|
||||
Map *map = &m_env->getMap();
|
||||
v3s16 size = content_mob_features(m_content).getSizeBlocks();
|
||||
for (int dx=0; dx<size.X; dx++)
|
||||
for (int dy=0; dy<size.Y; dy++)
|
||||
for (int dz=0; dz<size.Z; dz++) {
|
||||
v3s16 dp(dx, dy, dz);
|
||||
v3s16 p = p0 + dp;
|
||||
MapNode n = map->getNodeNoEx(p);
|
||||
if(n.getContent() != CONTENT_AIR)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool MobSAO::checkWalkablePosition(v3s16 p0)
|
||||
{
|
||||
assert(m_env);
|
||||
v3s16 p = p0 + v3s16(0,-1,0);
|
||||
MapNode n = m_env->getMap().getNodeNoEx(p);
|
||||
if (n.getContent() != CONTENT_AIR)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool MobSAO::checkFreeAndWalkablePosition(v3s16 p0)
|
||||
{
|
||||
if (!checkFreePosition(p0))
|
||||
return false;
|
||||
if (!checkWalkablePosition(p0))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
void MobSAO::explodeSquare(v3s16 p0, v3s16 size)
|
||||
{
|
||||
assert(m_env);
|
||||
Map *map = &m_env->getMap();
|
||||
core::map<v3s16, MapBlock*> modified_blocks;
|
||||
|
||||
for (int dx=0; dx<size.X; dx++)
|
||||
for (int dy=0; dy<size.Y; dy++)
|
||||
for (int dz=0; dz<size.Z; dz++) {
|
||||
v3s16 dp(dx - size.X/2, dy - size.Y/2, dz - size.Z/2);
|
||||
v3s16 p = p0 + dp;
|
||||
MapNode n = map->getNodeNoEx(p);
|
||||
if (n.getContent() == CONTENT_IGNORE)
|
||||
continue;
|
||||
if (content_features(n).pressure_type == CST_SOLID && content_features(n).draw_type == CDT_CUBELIKE)
|
||||
continue;
|
||||
map->removeNodeAndUpdate(p, modified_blocks);
|
||||
}
|
||||
|
||||
// Send a MEET_OTHER event
|
||||
MapEditEvent event;
|
||||
event.type = MEET_OTHER;
|
||||
for (core::map<v3s16, MapBlock*>::Iterator i = modified_blocks.getIterator(); i.atEnd() == false; i++) {
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
event.modified_blocks.insert(p, true);
|
||||
}
|
||||
map->dispatchEvent(&event);
|
||||
}
|
||||
InventoryItem* MobSAO::createPickedUpItem()
|
||||
{
|
||||
MobFeatures m = content_mob_features(m_content);
|
||||
if (m.punch_action != MPA_PICKUP) {
|
||||
if (!m_removed)
|
||||
return NULL;
|
||||
}
|
||||
if (m.dropped_item == "")
|
||||
return NULL;
|
||||
std::istringstream is(m.dropped_item, std::ios_base::binary);
|
||||
InventoryItem *item = InventoryItem::deSerialize(is);
|
||||
return item;
|
||||
}
|
||||
u16 MobSAO::punch(const std::string &toolname, v3f dir, const std::string &playername)
|
||||
{
|
||||
MobFeatures m = content_mob_features(m_content);
|
||||
if (m.punch_action == MPA_IGNORE)
|
||||
return 0;
|
||||
|
||||
actionstream<<playername<<" punches mob id="<<m_id
|
||||
<<" with a \""<<toolname<<"\" at "
|
||||
<<PP(m_base_position/BS)<<std::endl;
|
||||
|
||||
if (m.punch_action == MPA_HARM) {
|
||||
m_disturb_timer = 0;
|
||||
m_disturbing_player = playername;
|
||||
m_next_pos_exists = false; // Cancel moving immediately
|
||||
|
||||
m_yaw = wrapDegrees_180(180./PI*atan2(dir.Z, dir.X) + 180.);
|
||||
v3f new_base_position = m_base_position + dir * BS;
|
||||
{
|
||||
v3s16 pos_i = floatToInt(new_base_position, BS);
|
||||
v3s16 pos_size_off(0,0,0);
|
||||
if (m.getSizeBlocks().X >= 2.5) {
|
||||
pos_size_off.X = -1;
|
||||
pos_size_off.Y = -1;
|
||||
}
|
||||
bool free = checkFreePosition(pos_i + pos_size_off);
|
||||
if(free)
|
||||
m_base_position = new_base_position;
|
||||
}
|
||||
sendPosition();
|
||||
|
||||
|
||||
ToolItemFeatures f = content_toolitem_features(toolname);
|
||||
u16 amount = 2;
|
||||
if (f.type == TT_SWORD) {
|
||||
amount = 4*((f.hardness/100)+1);
|
||||
}else if (f.type == TT_AXE || f.type == TT_PICK) {
|
||||
amount = 2*((f.hardness/200)+1);
|
||||
}
|
||||
doDamage(amount);
|
||||
}else if (m.punch_action == MPA_DIE) {
|
||||
m_hp = 0;
|
||||
m_removed = true;
|
||||
}
|
||||
|
||||
return 655;
|
||||
}
|
||||
u8 MobSAO::level()
|
||||
{
|
||||
return content_mob_features(m_content).level;
|
||||
}
|
||||
void MobSAO::sendPosition()
|
||||
{
|
||||
m_last_sent_position = m_base_position;
|
||||
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// command (0 = update position)
|
||||
writeU8(os, 0);
|
||||
// pos
|
||||
writeV3F1000(os, m_base_position);
|
||||
// yaw
|
||||
writeF1000(os, m_yaw);
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), false, os.str());
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
void MobSAO::doDamage(u16 d)
|
||||
{
|
||||
infostream<<"MobV2 hp="<<m_hp<<" damage="<<d<<std::endl;
|
||||
|
||||
if (d < m_hp) {
|
||||
m_hp -= d;
|
||||
}else{
|
||||
actionstream<<"A "<<mobLevelS(content_mob_features(m_content).level)
|
||||
<<" mob id="<<m_id<<" dies at "<<PP(m_base_position)<<std::endl;
|
||||
// Die
|
||||
m_hp = 0;
|
||||
m_removed = true;
|
||||
}
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// command (1 = damage)
|
||||
writeU8(os, 1);
|
||||
// amount
|
||||
writeU16(os, d);
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), false, os.str());
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,22 +21,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#define CONTENT_SAO_HEADER
|
||||
|
||||
#include "serverobject.h"
|
||||
#include "mapnode.h"
|
||||
#include "content_object.h"
|
||||
|
||||
class TestSAO : public ServerActiveObject
|
||||
{
|
||||
public:
|
||||
TestSAO(ServerEnvironment *env, u16 id, v3f pos);
|
||||
u8 getType() const
|
||||
{return ACTIVEOBJECT_TYPE_TEST;}
|
||||
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
|
||||
const std::string &data);
|
||||
void step(float dtime, bool send_recommended);
|
||||
private:
|
||||
float m_timer1;
|
||||
float m_age;
|
||||
};
|
||||
|
||||
class ItemSAO : public ServerActiveObject
|
||||
{
|
||||
public:
|
||||
|
@ -195,5 +182,60 @@ private:
|
|||
Settings *m_properties;
|
||||
};
|
||||
|
||||
class MobSAO : public ServerActiveObject
|
||||
{
|
||||
public:
|
||||
MobSAO(ServerEnvironment *env, u16 id, v3f pos, content_t type);
|
||||
MobSAO(ServerEnvironment *env, u16 id, v3f pos, v3f speed, content_t type);
|
||||
virtual ~MobSAO();
|
||||
u8 getType() const {return ACTIVEOBJECT_TYPE_MOB;}
|
||||
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
|
||||
const std::string &data);
|
||||
std::string getStaticData();
|
||||
std::string getClientInitializationData();
|
||||
void step(float dtime, bool send_recommended);
|
||||
InventoryItem* createPickedUpItem();
|
||||
u16 punch(const std::string &toolname, v3f dir, const std::string &playername);
|
||||
u8 level();
|
||||
private:
|
||||
void sendPosition();
|
||||
void doDamage(u16 d);
|
||||
|
||||
void stepMotionWander(float dtime);
|
||||
void stepMotionSeeker(float dtime);
|
||||
void stepMotionSentry(float dtime);
|
||||
void stepMotionThrown(float dtime);
|
||||
void stepMotionConstant(float dtime);
|
||||
|
||||
bool checkFreePosition(v3s16 p0);
|
||||
bool checkWalkablePosition(v3s16 p0);
|
||||
bool checkFreeAndWalkablePosition(v3s16 p0);
|
||||
void explodeSquare(v3s16 p0, v3s16 size);
|
||||
|
||||
content_t m_content;
|
||||
v3f m_speed;
|
||||
v3f m_last_sent_position;
|
||||
v3f m_oldpos;
|
||||
float m_yaw;
|
||||
bool m_touching_ground;
|
||||
bool m_falling;
|
||||
bool m_next_pos_exists;
|
||||
v3s16 m_next_pos_i;
|
||||
|
||||
float m_age;
|
||||
int m_hp;
|
||||
|
||||
float m_disturb_timer;
|
||||
std::string m_disturbing_player;
|
||||
float m_random_disturb_timer;
|
||||
|
||||
bool m_walk_around;
|
||||
float m_walk_around_timer;
|
||||
float m_shoot_reload_timer;
|
||||
bool m_shooting;
|
||||
float m_shooting_timer;
|
||||
float m_shoot_y;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue