Send(0, data, true);
}
-void Client::clickActiveObject(u8 button, u16 id, u16 item)
+void Client::clickActiveObject(u8 button, u16 id, u16 item_i)
{
if(connectedAndInitialized() == false){
dout_client<<DTIME<<"Client::clickActiveObject() "
<<std::endl;
return;
}
+
+ Player *player = m_env.getLocalPlayer();
+ if(player == NULL)
+ return;
+
+ ClientActiveObject *obj = m_env.getActiveObject(id);
+ if(obj){
+ if(button == 0){
+ ToolItem *titem = NULL;
+ std::string toolname = "";
+
+ InventoryList *mlist = player->inventory.getList("main");
+ if(mlist != NULL)
+ {
+ InventoryItem *item = mlist->getItem(item_i);
+ if(item && (std::string)item->getName() == "ToolItem")
+ {
+ titem = (ToolItem*)item;
+ toolname = titem->getToolName();
+ }
+ }
+
+ v3f playerpos = player->getPosition();
+ v3f objpos = obj->getPosition();
+ v3f dir = (objpos - playerpos).normalize();
+
+ bool disable_send = obj->directReportPunch(toolname, dir);
+
+ if(disable_send)
+ return;
+ }
+ }
/*
length: 7
writeU16(&data[0], TOSERVER_CLICK_ACTIVEOBJECT);
writeU8(&data[2], button);
writeU16(&data[3], id);
- writeU16(&data[5], item);
+ writeU16(&data[5], item_i);
Send(0, data, true);
}
void groundAction(u8 action, v3s16 nodepos_undersurface,
v3s16 nodepos_oversurface, u16 item);
- void clickActiveObject(u8 button, u16 id, u16 item);
+ void clickActiveObject(u8 button, u16 id, u16 item_i);
void sendSignNodeText(v3s16 p, std::string text);
void sendInventoryAction(InventoryAction *a);
virtual void processMessage(const std::string &data){}
virtual std::string infoText() {return "";}
-
+
/*
This takes the return value of
ServerActiveObject::getClientInitializationData
// Create a certain type of ClientActiveObject
static ClientActiveObject* create(u8 type);
+ // If returns true, punch will not be sent to the server
+ virtual bool directReportPunch(const std::string &toolname, v3f dir)
+ { return false; }
+
protected:
// Used for creating objects based on type
typedef ClientActiveObject* (*Factory)();
m_last_light(0),
m_shooting(0),
m_shooting_unset_timer(0),
+ m_sprite_size(BS,BS),
+ m_sprite_y(0),
m_bright_shooting(false),
+ m_lock_full_brightness(false),
m_player_hit_timer(0)
{
ClientActiveObject::registerType(getType(), create);
if(m_node != NULL)
return;
- std::string texture_name = m_properties->get("texture_name");
- //dstream<<"MobV2CAO::addToScene using texture_name="<<texture_name<<std::endl;
+ /*dstream<<"MobV2CAO::addToScene using texture_name="<<
+ m_texture_name<<std::endl;*/
std::string texture_string = "[makealpha2:128,0,0;128,128,0:";
- texture_string += texture_name;
+ texture_string += m_texture_name;
scene::MyBillboardSceneNode *bill = new scene::MyBillboardSceneNode(
smgr->getRootSceneNode(), smgr, -1, v3f(0,0,0), v2f(1,1));
if(m_node == NULL)
return;
- m_node->setPosition(pos_translator.vect_show + m_sprite_pos);
+ m_node->setPosition(pos_translator.vect_show + v3f(0,m_sprite_y,0));
}
void MobV2CAO::step(float dtime, ClientEnvironment *env)
{
//u16 damage = readU16(is);
- u8 li = decode_light(m_last_light);
+ /*u8 li = decode_light(m_last_light);
if(li >= 100)
li = 30;
else
- li = 255;
- video::SColor color(255,li,li,li);
+ li = 255;*/
+
+ /*video::SColor color(255,255,0,0);
m_node->setColor(color);
- m_damage_visual_timer = 0.2;
+ m_damage_visual_timer = 0.2;*/
}
// Trigger shooting
else if(cmd == 2)
std::istringstream tmp_is(tmp_os.str(), std::ios::binary);
m_properties->parseConfigLines(tmp_is, "MobArgsEnd");
- /*dstream<<"INFO: MobV2CAO::initialize(): got properties:"<<std::endl;
- m_properties->writeLines(dstream);*/
-
- m_properties->setDefault("texture_name", "stone.png");
+ dstream<<"INFO: MobV2CAO::initialize(): got properties:"<<std::endl;
+ m_properties->writeLines(dstream);
+
+ m_properties->setDefault("looks", "dummy_default");
m_properties->setDefault("yaw", "0");
m_properties->setDefault("pos", "(0,0,0)");
- m_properties->setDefault("sprite_size", "(1,1)");
- m_properties->setDefault("sprite_pos", "(0,0,0)");
- m_properties->setDefault("selection_size", "(0.4,0.4)");
- m_properties->setDefault("selection_y", "-0.4");
- m_properties->setDefault("sprite_type", "humanoid_1");
- m_properties->setDefault("simple_anim_frames", "1");
- m_properties->setDefault("simple_anim_frametime", "0.5");
- m_properties->setDefault("lock_full_brightness", "false");
m_properties->setDefault("player_hit_damage", "0");
m_properties->setDefault("player_hit_distance", "1.5");
m_properties->setDefault("player_hit_interval", "1.5");
+ setLooks(m_properties->get("looks"));
m_yaw = m_properties->getFloat("yaw");
m_position = m_properties->getV3F("pos");
- m_sprite_size = m_properties->getV2F("sprite_size") * BS;
- m_sprite_pos = m_properties->getV3F("sprite_pos") * BS;
- v2f selection_size = m_properties->getV2F("selection_size") * BS;
- float selection_y = m_properties->getFloat("selection_y") * BS;
- m_selection_box = core::aabbox3d<f32>(
- -selection_size.X, selection_y, -selection_size.X,
- selection_size.X, selection_y+selection_size.Y,
- selection_size.X);
- m_sprite_type = m_properties->get("sprite_type");
- m_simple_anim_frames = m_properties->getS32("simple_anim_frames");
- m_simple_anim_frametime = m_properties->getFloat("simple_anim_frametime");
- m_lock_full_brightness = m_properties->getBool("lock_full_brightness");
m_player_hit_damage = m_properties->getS32("player_hit_damage");
m_player_hit_distance = m_properties->getFloat("player_hit_distance");
m_player_hit_interval = m_properties->getFloat("player_hit_interval");
updateNodePos();
}
+bool MobV2CAO::directReportPunch(const std::string &toolname, v3f dir)
+{
+ video::SColor color(255,255,0,0);
+ m_node->setColor(color);
+
+ m_damage_visual_timer = 0.05;
+
+ m_position += dir * BS;
+ pos_translator.sharpen();
+ pos_translator.update(m_position);
+ updateNodePos();
+
+ return false;
+}
+
+void MobV2CAO::setLooks(const std::string &looks)
+{
+ v2f selection_size = v2f(0.4, 0.4) * BS;
+ float selection_y = 0 * BS;
+
+ if(looks == "dungeon_master"){
+ m_texture_name = "dungeon_master.png";
+ m_sprite_type = "humanoid_1";
+ m_sprite_size = v2f(2, 3) * BS;
+ m_sprite_y = 0.85 * BS;
+ selection_size = v2f(0.4, 2.6) * BS;
+ selection_y = -0.4 * BS;
+ }
+ else if(looks == "fireball"){
+ m_texture_name = "fireball.png";
+ m_sprite_type = "simple";
+ m_sprite_size = v2f(1, 1) * BS;
+ m_simple_anim_frames = 3;
+ m_simple_anim_frametime = 0.1;
+ m_lock_full_brightness = true;
+ }
+ else{
+ m_texture_name = "stone.png";
+ m_sprite_type = "simple";
+ m_sprite_size = v2f(1, 1) * BS;
+ m_simple_anim_frames = 3;
+ m_simple_anim_frametime = 0.333;
+ selection_size = v2f(0.4, 0.4) * BS;
+ selection_y = 0 * BS;
+ }
+
+ m_selection_box = core::aabbox3d<f32>(
+ -selection_size.X, selection_y, -selection_size.X,
+ selection_size.X, selection_y+selection_size.Y,
+ selection_size.X);
+}
struct SmoothTranslator
{
v3f vect_old;
+ v3f vect_show;
+ v3f vect_aim;
f32 anim_counter;
f32 anim_time;
f32 anim_time_counter;
- v3f vect_show;
- v3f vect_aim;
SmoothTranslator():
vect_old(0,0,0),
+ vect_show(0,0,0),
+ vect_aim(0,0,0),
anim_counter(0),
anim_time(0),
- anim_time_counter(0),
- vect_show(0,0,0),
- vect_aim(0,0,0)
+ anim_time_counter(0)
{}
void init(v3f vect)
vect_old = vect;
vect_show = vect;
vect_aim = vect;
+ anim_counter = 0;
+ anim_time = 0;
+ anim_time_counter = 0;
+ }
+
+ void sharpen()
+ {
+ init(vect_show);
}
void update(v3f vect_new)
//{return m_position;}
bool doShowSelectionBox(){return false;}
+ // 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::MyBillboardSceneNode *m_node;
v3f m_position;
+ std::string m_texture_name;
float m_yaw;
SmoothTranslator pos_translator;
bool m_walking;
bool m_shooting;
float m_shooting_unset_timer;
v2f m_sprite_size;
- v3f m_sprite_pos;
+ float m_sprite_y;
bool m_bright_shooting;
std::string m_sprite_type;
int m_simple_anim_frames;
m_shoot_reload_timer(0),
m_shooting(false),
m_shooting_timer(0),
- m_falling(false)
+ m_falling(false),
+ m_disturb_timer(100000)
{
ServerActiveObject::registerType(getType(), create);
m_removed = true;
return;
}
+
+ Player *disturbing_player =
+ m_env->getPlayer(m_disturbing_player.c_str());
+ v3f disturbing_player_off = v3f(0,1,0);
+ float disturbing_player_distance = 1000000;
+ float disturbing_player_dir = 0;
+ if(disturbing_player){
+ disturbing_player_off =
+ disturbing_player->getPosition() - m_base_position;
+ disturbing_player_distance = disturbing_player_off.getLength();
+ disturbing_player_off.normalize();
+ disturbing_player_dir = 180./M_PI*atan2(disturbing_player_off.Z,
+ disturbing_player_off.X);
+ }
+
+ m_disturb_timer += dtime;
if(!m_falling)
{
dstream<<__FUNCTION_NAME<<": Shooting fireball from "<<PP(pos)
<<" at speed "<<PP(speed)<<std::endl;
Settings properties;
+ properties.set("looks", "fireball");
properties.setV3F("speed", speed);
properties.setFloat("die_age", 5.0);
properties.set("move_type", "constant_speed");
- properties.set("texture_name", "fireball.png");
- properties.setV3F("sprite_pos", v3f(0.0, 0.0, 0.0));
- properties.setV2F("sprite_size", v2f(1.0, 1.0));
- properties.set("sprite_type", "simple");
- properties.set("simple_anim_frames", "3");
- properties.set("simple_anim_frametime", "0.1");
properties.setFloat("hp", 1000);
properties.set("lock_full_brightness", "true");
properties.set("player_hit_damage", "9");
m_shoot_reload_timer += dtime;
- if(m_shoot_reload_timer >= 5.0 && !m_next_pos_exists)
+ float reload_time = 15.0;
+ if(m_disturb_timer <= 15.0)
+ reload_time = 3.0;
+
+ if(m_shoot_reload_timer >= reload_time && !m_next_pos_exists)
{
+ if(m_disturb_timer < 30.0 && disturbing_player &&
+ disturbing_player_distance < 16*BS &&
+ fabs(disturbing_player_off.Y) < 5*BS){
+ m_yaw = disturbing_player_dir;
+ sendPosition();
+ }
m_shoot_reload_timer = 0.0;
m_shooting = true;
m_shooting_timer = 1.5;
if(m_base_position.getDistanceFrom(m_last_sent_position) > 0.05*BS)
{
- 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);
+ sendPosition();
}
}
-u16 MobV2SAO::punch(const std::string &toolname, v3f dir)
+u16 MobV2SAO::punch(const std::string &toolname, v3f dir,
+ const std::string &playername)
{
+ assert(m_env);
+ Map *map = &m_env->getMap();
+
+ m_disturb_timer = 0;
+ m_disturbing_player = playername;
+
+ m_yaw = wrapDegrees_180(180./M_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 size_blocks = v3s16(m_size.X+0.5,m_size.Y+0.5,m_size.X+0.5);
+ v3s16 pos_size_off(0,0,0);
+ if(m_size.X >= 2.5){
+ pos_size_off.X = -1;
+ pos_size_off.Y = -1;
+ }
+ bool free = checkFreePosition(map, pos_i + pos_size_off, size_blocks);
+ if(free)
+ m_base_position = new_base_position;
+ }
+ sendPosition();
+
u16 amount = 2;
dstream<<"id="<<m_id<<": punch with \""<<toolname<<"\""<<std::endl;
/* See tool names in inventory.h */
return 65536/100;
}
+void MobV2SAO::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 MobV2SAO::setPropertyDefaults()
{
m_properties->setDefault("move_type", "ground_nodes");
std::string getClientInitializationData();
void step(float dtime, bool send_recommended);
InventoryItem* createPickedUpItem(){return NULL;}
- u16 punch(const std::string &toolname, v3f dir);
+ u16 punch(const std::string &toolname, v3f dir,
+ const std::string &playername);
private:
+ void sendPosition();
void setPropertyDefaults();
void readProperties();
void updateProperties();
float m_die_age;
v2f m_size;
bool m_falling;
+ float m_disturb_timer;
+ std::string m_disturbing_player;
Settings *m_properties;
};
static void getMob_dungeon_master(Settings &properties)
{
- properties.set("texture_name", "dungeon_master.png");
- properties.setV3F("sprite_pos", v3f(0.0, 0.85, 0.0));
- properties.setV2F("sprite_size", v2f(2.0, 3.0));
- properties.setFloat("selection_y", -0.4);
- properties.setV2F("selection_size", v2f(0.4, 2.6));
+ properties.set("looks", "dungeon_master");
properties.setFloat("yaw", 1.57);
properties.setFloat("hp", 20);
properties.setBool("bright_shooting", true);
properties.set("shoot_type", "fireball");
properties.set("shoot_y", "0.7");
- properties.set("sprite_type", "humanoid_1");
properties.set("player_hit_damage", "1");
properties.set("player_hit_distance", "1.0");
properties.set("player_hit_interval", "0.5");
//if(input->getLeftClicked())
if(input->getLeftState())
{
+ bool do_punch = false;
+ bool do_punch_damage = false;
if(object_hit_delay_timer <= 0.0){
+ do_punch = true;
+ do_punch_damage = true;
+ object_hit_delay_timer = object_hit_delay;
+ }
+ if(input->getLeftClicked()){
+ do_punch = true;
+ }
+ if(do_punch){
dstream<<DTIME<<"Left-clicked object"<<std::endl;
+ left_punch = true;
+ }
+ if(do_punch_damage){
client.clickActiveObject(0,
selected_active_object->getId(), g_selected_item);
- object_hit_delay_timer = object_hit_delay;
- left_punch = true;
- } else {
- dstream<<DTIME<<"Left-clicked object faster than allowed"
- <<std::endl;
- left_punch_muted = true;
}
}
else if(input->getRightClicked())
v3f objpos = obj->getBasePosition();
v3f dir = (objpos - playerpos).normalize();
- u16 wear = obj->punch(toolname, dir);
+ u16 wear = obj->punch(toolname, dir, player->getName());
if(titem)
{
If the object doesn't return an item, this will be called.
Return value is tool wear.
*/
- virtual u16 punch(const std::string &toolname, v3f dir)
+ virtual u16 punch(const std::string &toolname, v3f dir,
+ const std::string &playername)
{return 0;}
/*