implement MobCAO

This commit is contained in:
darkrose 2014-09-27 01:33:28 +10:00
parent 39a8e40aff
commit ab27c517f5
15 changed files with 684 additions and 2692 deletions

View File

@ -134,7 +134,6 @@ set(common_SRCS
log.cpp
content_sao.cpp
mapgen.cpp
content_inventory.cpp
content_nodemeta.cpp
content_craft.cpp
content_craftitem.cpp

View File

@ -1306,6 +1306,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
is.read(buf, 1);
u8 type = readU8((u8*)buf);
std::string data = deSerializeLongString(is);
printf("mob add: %d %d\n",id,type);
// Add it
{
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "clientobject.h"
#include "content_object.h"
#include "utility.h" // For IntervalLimiter
#include "mapnode.h"
#include "content_mob.h"
class Settings;
#include <IBillboardSceneNode.h>
@ -96,39 +98,6 @@ struct SmoothTranslator
}
};
/*
TestCAO
*/
class TestCAO : public ClientActiveObject
{
public:
TestCAO();
virtual ~TestCAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_TEST;
}
static ClientActiveObject* create();
void addToScene(scene::ISceneManager *smgr);
void removeFromScene();
void updateLight(u8 light_at_pos);
v3s16 getLightPosition();
void updateNodePos();
void step(float dtime, ClientEnvironment *env);
void processMessage(const std::string &data);
private:
scene::IMeshSceneNode *m_node;
v3f m_position;
};
/*
ItemCAO
*/
@ -158,10 +127,8 @@ public:
void initialize(const std::string &data);
core::aabbox3d<f32>* getSelectionBox()
{return &m_selection_box;}
v3f getPosition()
{return m_position;}
core::aabbox3d<f32>* getSelectionBox() {return &m_selection_box;}
v3f getPosition() {return m_position;}
void updateCameraOffset(v3s16 camera_offset)
{
@ -177,18 +144,18 @@ private:
};
/*
RatCAO
MobCAO
*/
class RatCAO : public ClientActiveObject
class MobCAO : public ClientActiveObject
{
public:
RatCAO();
virtual ~RatCAO();
MobCAO();
virtual ~MobCAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_RAT;
return ACTIVEOBJECT_TYPE_MOB;
}
static ClientActiveObject* create();
@ -205,160 +172,8 @@ public:
void initialize(const std::string &data);
core::aabbox3d<f32>* getSelectionBox()
{return &m_selection_box;}
v3f getPosition()
{return pos_translator.vect_show;}
void updateCameraOffset(v3s16 camera_offset)
{
m_camera_offset = camera_offset;
}
private:
core::aabbox3d<f32> m_selection_box;
scene::IAnimatedMeshSceneNode *m_node;
v3f m_position;
v3s16 m_camera_offset;
float m_yaw;
SmoothTranslator pos_translator;
};
/*
Oerkki1CAO
*/
class Oerkki1CAO : public ClientActiveObject
{
public:
Oerkki1CAO();
virtual ~Oerkki1CAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_OERKKI1;
}
static ClientActiveObject* create();
void addToScene(scene::ISceneManager *smgr);
void removeFromScene();
void updateLight(u8 light_at_pos);
v3s16 getLightPosition();
void updateNodePos();
void step(float dtime, ClientEnvironment *env);
void processMessage(const std::string &data);
void initialize(const std::string &data);
core::aabbox3d<f32>* getSelectionBox()
{return &m_selection_box;}
v3f getPosition()
{return pos_translator.vect_show;}
void updateCameraOffset(v3s16 camera_offset)
{
m_camera_offset = camera_offset;
}
// If returns true, punch will not be sent to the server
bool directReportPunch(const std::string &toolname, v3f dir);
private:
IntervalLimiter m_attack_interval;
core::aabbox3d<f32> m_selection_box;
scene::IAnimatedMeshSceneNode *m_node;
v3f m_position;
v3s16 m_camera_offset;
float m_yaw;
SmoothTranslator pos_translator;
float m_damage_visual_timer;
bool m_damage_texture_enabled;
};
/*
FireflyCAO
*/
class FireflyCAO : public ClientActiveObject
{
public:
FireflyCAO();
virtual ~FireflyCAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_FIREFLY;
}
static ClientActiveObject* create();
void addToScene(scene::ISceneManager *smgr);
void removeFromScene();
void updateLight(u8 light_at_pos);
v3s16 getLightPosition();
void updateNodePos();
void step(float dtime, ClientEnvironment *env);
void processMessage(const std::string &data);
void initialize(const std::string &data);
core::aabbox3d<f32>* getSelectionBox()
{return &m_selection_box;}
v3f getPosition()
{return m_position;}
void updateCameraOffset(v3s16 camera_offset)
{
m_camera_offset = camera_offset;
}
private:
core::aabbox3d<f32> m_selection_box;
scene::IMeshSceneNode *m_node;
v3f m_position;
v3s16 m_camera_offset;
float m_yaw;
SmoothTranslator pos_translator;
};
/*
MobV2CAO
*/
class MobV2CAO : public ClientActiveObject
{
public:
MobV2CAO();
virtual ~MobV2CAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_MOBV2;
}
static ClientActiveObject* create();
void addToScene(scene::ISceneManager *smgr);
void removeFromScene();
void updateLight(u8 light_at_pos);
v3s16 getLightPosition();
void updateNodePos();
void step(float dtime, ClientEnvironment *env);
void processMessage(const std::string &data);
void initialize(const std::string &data);
core::aabbox3d<f32>* getSelectionBox()
{return &m_selection_box;}
v3f getPosition()
{return pos_translator.vect_show;}
core::aabbox3d<f32>* getSelectionBox() {m_selection_box = content_mob_features(m_content).getCollisionBox(); return &m_selection_box;}
v3f getPosition() {return pos_translator.vect_show;}
void updateCameraOffset(v3s16 camera_offset)
{
@ -368,39 +183,21 @@ public:
// If returns true, punch will not be sent to the server
bool directReportPunch(const std::string &toolname, v3f dir);
private:
void setLooks(const std::string &looks);
IntervalLimiter m_attack_interval;
core::aabbox3d<f32> m_selection_box;
scene::IBillboardSceneNode *m_node;
aabb3f m_selection_box;
content_t m_content;
scene::IAnimatedMeshSceneNode *m_node;
v3f m_position;
v3s16 m_camera_offset;
std::string m_texture_name;
float m_yaw;
SmoothTranslator pos_translator;
bool m_walking;
float m_walking_unset_timer;
float m_walk_timer;
int m_walk_frame;
float m_damage_visual_timer;
u8 m_last_light;
float m_player_hit_timer;
float m_damage_visual_timer;
bool m_shooting;
float m_shooting_unset_timer;
v2f m_sprite_size;
float m_sprite_y;
bool m_bright_shooting;
std::string m_sprite_type;
int m_simple_anim_frames;
float m_simple_anim_frametime;
bool m_lock_full_brightness;
int m_player_hit_damage;
float m_player_hit_distance;
float m_player_hit_interval;
float m_player_hit_timer;
Settings *m_properties;
bool m_walking;
float m_walking_unset_timer;
};

View File

@ -1,44 +0,0 @@
/*
Minetest-c55
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "content_inventory.h"
#include "inventory.h"
#include "content_mapnode.h"
//#include "serverobject.h"
#include "content_sao.h"
ServerActiveObject* item_craft_create_object(const std::string &subname,
ServerEnvironment *env, u16 id, v3f pos)
{
if(subname == "rat")
{
ServerActiveObject *obj = new RatSAO(env, id, pos);
return obj;
}
else if(subname == "firefly")
{
ServerActiveObject *obj = new FireflySAO(env, id, pos);
return obj;
}
return NULL;
}

View File

@ -1,35 +0,0 @@
/*
Minetest-c55
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef CONTENT_INVENTORY_HEADER
#define CONTENT_INVENTORY_HEADER
#include "common_irrlicht.h" // For u8, s16
#include <string>
#include "mapnode.h" // For content_t
class InventoryItem;
class ServerActiveObject;
class ServerEnvironment;
ServerActiveObject* item_craft_create_object(const std::string &subname,
ServerEnvironment *env, u16 id, v3f pos);
#endif

View File

@ -19,8 +19,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>
************************************************************************/
#include "serverobject.h"
#include "content_sao.h"
#include "content_mob.h"
#include "main.h"
#include "settings.h"
#include "environment.h"
#include "map.h"
std::map<content_t,struct MobFeatures> g_content_mob_features;
@ -52,6 +57,116 @@ void MobFeatures::setBoxTexture(u16 i, std::string name, u8 alpha)
}
}
#endif
void MobFeatures::getAnimationFrames(MobAnimation type, int *start, int *end)
{
*start = 0;
*end = 0;
switch (type) {
case MA_STAND:
*start = animations[MA_STAND_START];
*end = animations[MA_STAND_END];
break;
case MA_MOVE:
*start = animations[MA_MOVE_START];
*end = animations[MA_MOVE_END];
break;
case MA_ATTACK:
*start = animations[MA_ATTACK_START];
*end = animations[MA_ATTACK_END];
break;
default:;
}
if (type != MA_STAND && start == end) {
*start = animations[MA_STAND_START];
*end = animations[MA_STAND_END];
}
}
void MobFeatures::setAnimationFrames(MobAnimation type, int start, int end)
{
switch (type) {
case MA_STAND:
animations[MA_STAND_START] = start;
animations[MA_STAND_END] = end;
break;
case MA_MOVE:
animations[MA_MOVE_START] = start;
animations[MA_MOVE_END] = end;
break;
case MA_ATTACK:
animations[MA_ATTACK_START] = start;
animations[MA_ATTACK_END] = end;
break;
default:;
}
}
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
bool content_mob_spawn(ServerEnvironment *env, v3s16 pos)
{
assert(env);
Map *map = &env->getMap();
std::vector<content_t> can;
MapNode n = map->getNodeNoEx(pos);
MapNode a1 = map->getNodeNoEx(pos+v3s16(0,1,0));
MapNode a2 = map->getNodeNoEx(pos+v3s16(0,2,0));
content_t c0 = n.getContent();
content_t c1 = a1.getContent();
content_t c2 = a2.getContent();
u8 light = n.getLightBlend(env->getDayNightRatio());
u8 level = mobLevelI(g_settings->get("max_mob_level"));
if (c0 == CONTENT_IGNORE || c1 == CONTENT_IGNORE || c2 == CONTENT_IGNORE)
return false;
for (std::map<content_t,struct MobFeatures>::iterator i = g_content_mob_features.begin(); i != g_content_mob_features.end(); i++) {
MobFeatures m = i->second;
if (m.spawn_in == CONTENT_IGNORE && m.spawn_on == CONTENT_IGNORE)
continue;
if (m.spawn_in != CONTENT_IGNORE) {
if (m.spawn_in != c1)
continue;
if (m.spawn_in != c2)
continue;
}
if (m.spawn_on != CONTENT_IGNORE) {
if (m.spawn_on != c0)
continue;
}
if (m.spawn_min_light > light)
continue;
if (m.spawn_max_light < light)
continue;
if (m.level > level)
continue;
can.push_back(i->first);
}
if (can.size() == 0)
return false;
MobFeatures m;
u32 index = 0;
if (can.size() > 1)
index = myrand_range(0,can.size()-1);
m = g_content_mob_features[can[index]];
if (m.content == CONTENT_IGNORE)
return false;
v3f p = intToFloat(pos+v3s16(0,1,0), BS);
actionstream<<"A mob of type "<<m.content<<" spawns at "<<PP(floatToInt(p,BS))<<std::endl;
ServerActiveObject *obj = new MobSAO(env, 0, p, m.content);
u16 id = env->addActiveObject(obj);
if (id)
return true;
actionstream<<"A mob of type "<<m.content<<" didn't spawn at "<<PP(floatToInt(p,BS))<<std::endl;
return false;
}
void content_mob_init()
{
@ -66,33 +181,40 @@ void content_mob_init()
f->level = MOB_PASSIVE;
f->model = "rat.x";
f->setTexture("mob_rat.png");
f->setAnimationFrames(MA_STAND,0,79);
f->punch_action = MPA_PICKUP;
f->motion = MM_WANDER;
f->spawn_on = CONTENT_GRASS;
f->spawn_in = CONTENT_AIR;
f->setCollisionBox(aabb3f(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.));
i = CONTENT_MOB_FIREFLY;
f = &g_content_mob_features[i];
f->content = i;
//f->content = i;
f->level = MOB_PASSIVE;
f->setTexture("mob_firefly.png");
f->punch_action = MPA_PICKUP;
f->motion = MM_WANDER;
f->glow_light = LIGHT_MAX-1;
f->spawn_on = CONTENT_JUNGLETREE;
f->spawn_in = CONTENT_AIR;
f->setCollisionBox(aabb3f(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.));
i = CONTENT_MOB_OERKKI;
f = &g_content_mob_features[i];
f->content = i;
//f->content = i;
f->level = MOB_AGGRESSIVE;
f->model = "oerkki.x";
f->setTexture("mob_oerkki.png");
f->setAnimationFrames(MA_STAND,24,36);
f->setAnimationFrames(MA_ATTACK,37,49);
f->punch_action = MPA_HARM;
f->motion = MM_SEEKER;
f->setCollisionBox(aabb3f(-BS/3.,0.0,-BS/3., BS/3.,BS*2.,BS/3.));
i = CONTENT_MOB_DUNGEON_MASTER;
f = &g_content_mob_features[i];
f->content = i;
//f->content = i;
f->level = MOB_DESTRUCTIVE;
f->model = "dungeon_master.x";
f->setTexture("mob_dungeon_master.png");
@ -104,7 +226,7 @@ void content_mob_init()
i = CONTENT_MOB_FIREBALL;
f = &g_content_mob_features[i];
f->content = i;
//f->content = i;
f->level = MOB_DESTRUCTIVE;
f->setTexture("mob_fireball.png");
f->punch_action = MPA_IGNORE;
@ -115,18 +237,18 @@ void content_mob_init()
i = CONTENT_MOB_DEER;
f = &g_content_mob_features[i];
f->content = i;
//f->content = i;
i = CONTENT_MOB_SHEEP;
f = &g_content_mob_features[i];
f->content = i;
//f->content = i;
i = CONTENT_MOB_FISH;
f = &g_content_mob_features[i];
f->content = i;
//f->content = i;
i = CONTENT_MOB_SHARK;
f = &g_content_mob_features[i];
f->content = i;
//f->content = i;
i = CONTENT_MOB_WOLF;
f = &g_content_mob_features[i];
f->content = i;
//f->content = i;
}

View File

@ -69,6 +69,16 @@ enum MobAnimation
MA_ATTACK
};
enum MobAnimationKey
{
MA_STAND_START = 0,
MA_STAND_END,
MA_MOVE_START,
MA_MOVE_END,
MA_ATTACK_START,
MA_ATTACK_END
};
#define CONTENT_MOB_MASK 0x2000
struct MobFeatures {
@ -79,7 +89,9 @@ struct MobFeatures {
video::ITexture *texture;
#endif
std::string model;
std::map<MobAnimation,int[2]> animations;
std::map<MobAnimationKey,int> animations;
v3f model_scale;
v3f model_offset;
std::vector<aabb3f> nodeboxes;
aabb3f collisionbox;
@ -93,6 +105,7 @@ struct MobFeatures {
content_t attack_throw_object;
v3f attack_throw_offset;
u8 attack_player_damage;
v3f attack_player_range;
u8 glow_light;
u8 attack_glow_light;
u16 hp;
@ -100,6 +113,11 @@ struct MobFeatures {
f32 lifetime;
u16 contact_explosion_diameter;
content_t spawn_on;
content_t spawn_in;
u8 spawn_min_light;
u8 spawn_max_light;
MobFeatures()
{
reset();
@ -153,6 +171,9 @@ struct MobFeatures {
return v3s16(s.X+0.5,s.Y+0.5,s.Z+0.5);
}
void getAnimationFrames(MobAnimation type, int *start, int *end);
void setAnimationFrames(MobAnimation type, int start, int end);
#ifdef SERVER
void setTexture(std::string name)
{}
@ -176,6 +197,8 @@ struct MobFeatures {
{
content = CONTENT_IGNORE;
model = "";
model_scale = v3f(0,0,0);
model_offset = v3f(0,0,0);
nodeboxes.clear();
punch_action = MPA_DIE;
motion = MM_STATIC;
@ -187,12 +210,17 @@ struct MobFeatures {
attack_throw_object = CONTENT_IGNORE;
attack_throw_offset = v3f(0,0,0);
attack_player_damage = 0;
attack_player_range = v3f(0,0,0);
glow_light = 0;
attack_glow_light = 0;
hp = 20;
dropped_item = "";
lifetime = 0.0;
contact_explosion_diameter = 0;
spawn_on = CONTENT_IGNORE;
spawn_in = CONTENT_IGNORE;
spawn_min_light = 0;
spawn_max_light = LIGHT_MAX;
}
};
@ -214,6 +242,9 @@ inline std::string mobLevelS(u8 level)
return std::string("passive");
}
class ServerEnvironment;
bool content_mob_spawn(ServerEnvironment *env, v3s16 pos);
MobFeatures & content_mob_features(content_t i);
void content_mob_init();

File diff suppressed because it is too large Load Diff

View File

@ -46,142 +46,6 @@ private:
IntervalLimiter m_move_interval;
};
class RatSAO : public ServerActiveObject
{
public:
RatSAO(ServerEnvironment *env, u16 id, v3f pos);
u8 getType() const
{return ACTIVEOBJECT_TYPE_RAT;}
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
const std::string &data);
void step(float dtime, bool send_recommended);
std::string getClientInitializationData();
std::string getStaticData();
InventoryItem* createPickedUpItem();
private:
bool m_is_active;
IntervalLimiter m_inactive_interval;
v3f m_speed_f;
v3f m_oldpos;
v3f m_last_sent_position;
float m_yaw;
float m_counter1;
float m_counter2;
float m_age;
bool m_touching_ground;
};
class Oerkki1SAO : public ServerActiveObject
{
public:
Oerkki1SAO(ServerEnvironment *env, u16 id, v3f pos);
u8 getType() const
{return ACTIVEOBJECT_TYPE_OERKKI1;}
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
const std::string &data);
void step(float dtime, bool send_recommended);
std::string getClientInitializationData();
std::string getStaticData();
InventoryItem* createPickedUpItem();
u16 punch(const std::string &toolname, v3f dir,
const std::string &playername);
u8 level(){return MOB_AGGRESSIVE;}
private:
void doDamage(u16 d);
bool m_is_active;
IntervalLimiter m_inactive_interval;
v3f m_speed_f;
v3f m_oldpos;
v3f m_last_sent_position;
float m_yaw;
float m_counter1;
float m_counter2;
float m_age;
bool m_touching_ground;
u8 m_hp;
float m_after_jump_timer;
};
class FireflySAO : public ServerActiveObject
{
public:
FireflySAO(ServerEnvironment *env, u16 id, v3f pos);
u8 getType() const
{return ACTIVEOBJECT_TYPE_FIREFLY;}
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
const std::string &data);
void step(float dtime, bool send_recommended);
std::string getClientInitializationData();
std::string getStaticData();
InventoryItem* createPickedUpItem();
private:
bool m_is_active;
IntervalLimiter m_inactive_interval;
v3f m_speed_f;
v3f m_oldpos;
v3f m_last_sent_position;
float m_yaw;
float m_counter1;
float m_counter2;
float m_age;
bool m_touching_ground;
};
class Settings;
class MobV2SAO : public ServerActiveObject
{
public:
MobV2SAO(ServerEnvironment *env, u16 id, v3f pos,
Settings *init_properties);
virtual ~MobV2SAO();
u8 getType() const
{return ACTIVEOBJECT_TYPE_MOBV2;}
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(){return NULL;}
u16 punch(const std::string &toolname, v3f dir,
const std::string &playername);
u8 level();
private:
void sendPosition();
void setPropertyDefaults();
void readProperties();
void updateProperties();
void doDamage(u16 d);
std::string m_move_type;
v3f m_speed;
v3f m_last_sent_position;
v3f m_oldpos;
float m_yaw;
float m_counter1;
float m_counter2;
float m_age;
bool m_touching_ground;
int m_hp;
bool m_walk_around;
float m_walk_around_timer;
bool m_next_pos_exists;
v3s16 m_next_pos_i;
float m_shoot_reload_timer;
bool m_shooting;
float m_shooting_timer;
float m_die_age;
v2f m_size;
bool m_falling;
float m_disturb_timer;
std::string m_disturbing_player;
float m_random_disturb_timer;
float m_shoot_y;
Settings *m_properties;
};
class MobSAO : public ServerActiveObject
{
public:
@ -216,6 +80,7 @@ private:
v3f m_speed;
v3f m_last_sent_position;
v3f m_oldpos;
v3f m_initial_pos;
float m_yaw;
bool m_touching_ground;
bool m_falling;
@ -223,7 +88,7 @@ private:
v3s16 m_next_pos_i;
float m_age;
int m_hp;
u8 m_hp;
float m_disturb_timer;
std::string m_disturbing_player;

View File

@ -542,56 +542,6 @@ void ServerEnvironment::loadMeta(const std::string &savedir)
}
}
#if 0
// This is probably very useless
void spawnRandomObjects(MapBlock *block)
{
for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
{
bool last_node_walkable = false;
for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
{
v3s16 p(x0,y0,z0);
MapNode n = block->getNodeNoEx(p);
if(n.getContent() == CONTENT_IGNORE)
continue;
if(content_features(n).liquid_type != LIQUID_NONE)
continue;
if(content_features(n).walkable)
{
last_node_walkable = true;
continue;
}
if(last_node_walkable)
{
// If block contains light information
if(content_features(n).param_type == CPT_LIGHT)
{
if(n.getLight(LIGHTBANK_DAY) <= 5)
{
if(myrand() % 1000 == 0)
{
v3f pos_f = intToFloat(p+block->getPosRelative(), BS);
pos_f.Y -= BS*0.4;
ServerActiveObject *obj = new Oerkki1SAO(NULL,0,pos_f);
std::string data = obj->getStaticData();
StaticObject s_obj(obj->getType(),
obj->getBasePosition(), data);
// Add one
block->m_static_objects.insert(0, s_obj);
delete obj;
block->setChangedFlag();
}
}
}
}
last_node_walkable = false;
}
}
}
#endif
void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
{
// Get time difference
@ -708,29 +658,6 @@ void ServerEnvironment::clearAllObjects()
<<" in "<<num_blocks_cleared<<" blocks"<<std::endl;
}
static void getMob_dungeon_master(Settings &properties)
{
properties.set("looks", "dungeon_master");
properties.set("visual", "mesh");
properties.set("visual_model","dungeon_master.x");
properties.set("visual_model_texture","dungeon_master_mob.png");
properties.set("visual_model_","");
properties.set("visual_sprite","dungeon_master.png");
properties.set("visual_sprite_size","(2.0,0.85,3.0)");
properties.set("visual_sprite_type","humanoid_1");
properties.set("visual_selection_size","(0.4,-0.4,2.6)");
properties.setFloat("yaw", 1.57);
properties.setFloat("hp", 30);
properties.setBool("bright_shooting", true);
properties.set("shoot_type", "fireball");
properties.set("shoot_y", "0.7");
properties.set("player_hit_damage", "1");
properties.set("player_hit_distance", "1.0");
properties.set("player_hit_interval", "0.5");
properties.set("level","destructive");
properties.setBool("mindless_rage", myrand_range(0,100)==0);
}
bool ServerEnvironment::searchNear(v3s16 pos, v3s16 radius_min, v3s16 radius_max, std::vector<content_t> c, v3s16 *found)
{
v3s16 blockpos = getNodeBlockPos(pos);
@ -1022,6 +949,11 @@ void ServerEnvironment::step(float dtime)
v3s16 p = p0 + block->getPosRelative();
MapNode n = block->getNodeNoEx(p0);
if (active_object_count_wider < 3 && myrand()%100 == 0) {
if (content_mob_spawn(this,p))
active_object_count_wider++;
}
switch(n.getContent()) {
case CONTENT_GRASS_FOOTSTEPS:
{
@ -2032,105 +1964,6 @@ void ServerEnvironment::step(float dtime)
break;
}
// Rats spawn around regular trees
case CONTENT_TREE:
case CONTENT_APPLE_TREE:
case CONTENT_CONIFER_TREE:
{
if(myrand()%200 == 0 && active_object_count_wider == 0)
{
v3s16 p1 = p + v3s16(myrand_range(-2, 2),
0, myrand_range(-2, 2));
MapNode n1 = m_map->getNodeNoEx(p1);
MapNode n1b = m_map->getNodeNoEx(p1+v3s16(0,-1,0));
if(n1b.getContent() == CONTENT_GRASS &&
n1.getContent() == CONTENT_AIR)
{
v3f pos = intToFloat(p1, BS);
ServerActiveObject *obj = new RatSAO(this, 0, pos);
addActiveObject(obj);
}
}
break;
}
// fireflies spawn in jungles at night
case CONTENT_JUNGLETREE:
{
if (myrand()%100 == 0 && active_object_count_wider < 10) {
v3s16 p1 = p + v3s16(myrand_range(-2, 2),
0, myrand_range(-2, 2));
MapNode n1 = m_map->getNodeNoEx(p1);
MapNode n1b = m_map->getNodeNoEx(p1+v3s16(0,-1,0));
if (
(
n1b.getContent() == CONTENT_AIR
|| n1b.getContent() == CONTENT_JUNGLETREE
|| n1b.getContent() == CONTENT_JUNGLEGRASS
)
&& n1.getContent() == CONTENT_AIR
&& n1.getLightBlend(getDayNightRatio()) <= LIGHT_MAX/2
) {
v3f pos = intToFloat(p1, BS);
ServerActiveObject *obj = new FireflySAO(this, 0, pos);
addActiveObject(obj);
}
}
break;
}
// Fun things spawn in caves and dungeons
case CONTENT_STONE:
case CONTENT_MOSSYCOBBLE:
{
if(myrand()%500 == 0 && active_object_count_wider == 0)
{
v3s16 p1 = p + v3s16(0,1,0);
MapNode n1a = m_map->getNodeNoEx(p1+v3s16(0,0,0));
if(n1a.getLightBlend(getDayNightRatio()) <= 3){
MapNode n1b = m_map->getNodeNoEx(p1+v3s16(0,1,0));
if(n1a.getContent() == CONTENT_AIR &&
n1b.getContent() == CONTENT_AIR)
{
v3f pos = intToFloat(p1, BS);
ServerActiveObject *obj;
Settings properties;
int i = myrand()%5;
u8 mob_level = mobLevelI(g_settings->get("max_mob_level"));
switch (i) {
case 0:
getMob_dungeon_master(properties);
if (mobLevelI(properties.get("level")) >= mob_level) {
actionstream<<"A dungeon master spawns at "
<<PP(p1)<<std::endl;
obj = new MobV2SAO(this, 0, pos, &properties);
addActiveObject(obj);
active_object_count_wider++;
}
break;
case 1:
actionstream<<"Rat spawns at "
<<PP(p1)<<std::endl;
obj = new RatSAO(this, 0, pos);
addActiveObject(obj);
active_object_count_wider++;
break;
case 2:
if (mob_level > MOB_PASSIVE) {
actionstream<<"An oerkki spawns at "
<<PP(p1)<<std::endl;
obj = new Oerkki1SAO(this, 0, pos);
addActiveObject(obj);
active_object_count_wider++;
}
break;
default:;
}
}
}
}
break;
}
// Make trees from saplings!
case CONTENT_SAPLING:
{
@ -3385,8 +3218,7 @@ ActiveObjectMessage ServerEnvironment::getActiveObjectMessage()
************ Private methods *************
*/
u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
bool set_changed)
u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object, bool set_changed)
{
assert(object);
if(object->getId() == 0){
@ -3434,7 +3266,7 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
object->m_static_exists = true;
object->m_static_block = blockpos;
if(set_changed)
if (set_changed)
block->raiseModified(MOD_STATE_WRITE_NEEDED);
}
else{
@ -4227,12 +4059,11 @@ u16 ClientEnvironment::addActiveObject(ClientActiveObject *object)
return object->getId();
}
void ClientEnvironment::addActiveObject(u16 id, u8 type,
const std::string &init_data)
void ClientEnvironment::addActiveObject(u16 id, u8 type, const std::string &init_data)
{
// TODO: convert old to new
ClientActiveObject* obj = ClientActiveObject::create(type);
if(obj == NULL)
{
if (obj == NULL) {
infostream<<"ClientEnvironment::addActiveObject(): "
<<"id="<<id<<" type="<<type<<": Couldn't create object"
<<std::endl;

View File

@ -234,9 +234,9 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
case GUI_ID_MOBS_AGGRESSIVE:
max_mob_level = L"aggressive";
break;
//case GUI_ID_MOBS_DESTRUCTIVE:
//max_mob_level = L"destructive";
//break;
case GUI_ID_MOBS_DESTRUCTIVE:
max_mob_level = L"destructive";
break;
default:
max_mob_level = L"aggressive";
}
@ -648,11 +648,11 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
gui::IGUIComboBox *c = Environment->addComboBox(rect, this, GUI_ID_MOBS_COMBO);
u32 pm = c->addItem(wgettext("Passive"),GUI_ID_MOBS_PASSIVE);
u32 am = c->addItem(wgettext("Passive & Aggressive"),GUI_ID_MOBS_AGGRESSIVE);
//u32 dm = c->addItem(wgettext("Passive, Aggressive, & Destructive"),GUI_ID_MOBS_DESTRUCTIVE);
u32 dm = c->addItem(wgettext("Passive, Aggressive, & Destructive"),GUI_ID_MOBS_DESTRUCTIVE);
if (max_mob_level == L"passive") {
c->setSelected(pm);
//}else if (max_mob_level == L"destructive") {
//c->setSelected(dm);
}else if (max_mob_level == L"destructive") {
c->setSelected(dm);
}else{
c->setSelected(am);
}
@ -947,8 +947,8 @@ void GUIMainMenu::acceptInput()
s32 i;
if (m_data->max_mob_level == L"passive") {
i = c->getIndexForItemData(GUI_ID_MOBS_PASSIVE);
//}else if (m_data->max_mob_level == L"destructive") {
//i = c->getIndexForItemData(GUI_ID_MOBS_DESTRUCTIVE);
}else if (m_data->max_mob_level == L"destructive") {
i = c->getIndexForItemData(GUI_ID_MOBS_DESTRUCTIVE);
}else{
i = c->getIndexForItemData(GUI_ID_MOBS_AGGRESSIVE);
}
@ -987,9 +987,9 @@ void GUIMainMenu::acceptInput()
case GUI_ID_MOBS_AGGRESSIVE:
m_data->max_mob_level = L"aggressive";
break;
//case GUI_ID_MOBS_DESTRUCTIVE:
//m_data->max_mob_level = L"destructive";
//break;
case GUI_ID_MOBS_DESTRUCTIVE:
m_data->max_mob_level = L"destructive";
break;
default:
m_data->max_mob_level = L"aggressive";
}

View File

@ -29,8 +29,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "main.h"
#include "serverobject.h"
#include "content_mapnode.h"
#include "content_inventory.h"
#include "content_sao.h"
#include "content_mob.h"
#include "player.h"
#include "log.h"
@ -206,9 +206,11 @@ std::wstring CraftItem::getGuiName()
ServerActiveObject* CraftItem::createSAO(ServerEnvironment *env, u16 id, v3f pos)
{
// Special cases
ServerActiveObject *obj = item_craft_create_object(m_subname, env, id, pos);
if(obj)
return obj;
if ((m_content&CONTENT_MOB_MASK) == CONTENT_MOB_MASK) {
ServerActiveObject *obj = new MobSAO(env,id,pos,m_content);
if (obj)
return obj;
}
// Default
return InventoryItem::createSAO(env, id, pos);
}

View File

@ -1388,21 +1388,19 @@ void Server::AsyncRunStep()
// Handle added objects
writeU16((u8*)buf, added_objects.size());
data_buffer.append(buf, 2);
for(core::map<u16, bool>::Iterator
i = added_objects.getIterator();
i.atEnd()==false; i++)
{
for (core::map<u16, bool>::Iterator i = added_objects.getIterator(); i.atEnd()==false; i++) {
// Get object
u16 id = i.getNode()->getKey();
ServerActiveObject* obj = m_env.getActiveObject(id);
// Get object type
u8 type = ACTIVEOBJECT_TYPE_INVALID;
if(obj == NULL)
if (obj == NULL) {
infostream<<"WARNING: "<<__FUNCTION_NAME
<<": NULL object"<<std::endl;
else
}else{
type = obj->getType();
}
// Add to data buffer for sending
writeU16((u8*)buf, id);
@ -1410,11 +1408,11 @@ void Server::AsyncRunStep()
writeU8((u8*)buf, type);
data_buffer.append(buf, 1);
if(obj)
data_buffer.append(serializeLongString(
obj->getClientInitializationData()));
else
if (obj) {
data_buffer.append(serializeLongString(obj->getClientInitializationData()));
}else{
data_buffer.append(serializeLongString(""));
}
// Add to known objects
client->m_known_objects.insert(i.getNode()->getKey(), false);
@ -1426,8 +1424,7 @@ void Server::AsyncRunStep()
// Send packet
SharedBuffer<u8> reply(2 + data_buffer.size());
writeU16(&reply[0], TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD);
memcpy((char*)&reply[2], data_buffer.c_str(),
data_buffer.size());
memcpy((char*)&reply[2], data_buffer.c_str(), data_buffer.size());
// Send as reliable
m_con.Send(client->peer_id, 0, reply, true);

View File

@ -239,12 +239,21 @@ inline void writeU16(std::ostream &os, u16 p)
writeU16((u8*)buf, p);
os.write(buf, 2);
}
inline void writeS16(std::ostream &os, s16 i){
writeU16(os, (u16)i);
}
inline u16 readU16(std::istream &is)
{
char buf[2];
is.read(buf, 2);
return readU16((u8*)buf);
}
inline u16 readS16(std::istream &is)
{
char buf[2];
is.read(buf, 2);
return readS16((u8*)buf);
}
inline void writeU32(std::ostream &os, u32 p)
{