Compare commits
12 Commits
stable-0.4
...
sapier-201
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c17133d80a | ||
|
|
14a64000ea | ||
|
|
e3122ae727 | ||
|
|
65ac1d46b3 | ||
|
|
dd73852ce4 | ||
|
|
3454e67793 | ||
|
|
0c78767754 | ||
|
|
f0679969b2 | ||
|
|
285f5a0259 | ||
|
|
71186974fa | ||
|
|
525bc8855f | ||
|
|
de166e75a1 |
@@ -107,6 +107,13 @@ set(common_SRCS
|
|||||||
scriptapi.cpp
|
scriptapi.cpp
|
||||||
script.cpp
|
script.cpp
|
||||||
log.cpp
|
log.cpp
|
||||||
|
content_sao_firefly.cpp
|
||||||
|
content_sao_item.cpp
|
||||||
|
content_sao_lua.cpp
|
||||||
|
content_sao_mobv2.cpp
|
||||||
|
content_sao_oerkki1.cpp
|
||||||
|
content_sao_rat.cpp
|
||||||
|
content_sao_test.cpp
|
||||||
content_sao.cpp
|
content_sao.cpp
|
||||||
mapgen.cpp
|
mapgen.cpp
|
||||||
content_nodemeta.cpp
|
content_nodemeta.cpp
|
||||||
@@ -115,6 +122,7 @@ set(common_SRCS
|
|||||||
collision.cpp
|
collision.cpp
|
||||||
nodemetadata.cpp
|
nodemetadata.cpp
|
||||||
serverobject.cpp
|
serverobject.cpp
|
||||||
|
serverlinkableobject.cpp
|
||||||
noise.cpp
|
noise.cpp
|
||||||
mineral.cpp
|
mineral.cpp
|
||||||
porting.cpp
|
porting.cpp
|
||||||
@@ -161,6 +169,14 @@ set(minetest_SRCS
|
|||||||
${common_SRCS}
|
${common_SRCS}
|
||||||
content_mapblock.cpp
|
content_mapblock.cpp
|
||||||
content_cao.cpp
|
content_cao.cpp
|
||||||
|
content_cao_player.cpp
|
||||||
|
content_cao_item.cpp
|
||||||
|
content_cao_lua.cpp
|
||||||
|
content_cao_rat.cpp
|
||||||
|
content_cao_oerkki1.cpp
|
||||||
|
content_cao_firefly.cpp
|
||||||
|
content_cao_mobv2.cpp
|
||||||
|
content_cao_test.cpp
|
||||||
mesh.cpp
|
mesh.cpp
|
||||||
mapblock_mesh.cpp
|
mapblock_mesh.cpp
|
||||||
farmesh.cpp
|
farmesh.cpp
|
||||||
@@ -168,6 +184,7 @@ set(minetest_SRCS
|
|||||||
camera.cpp
|
camera.cpp
|
||||||
clouds.cpp
|
clouds.cpp
|
||||||
clientobject.cpp
|
clientobject.cpp
|
||||||
|
clientlinkableobject.cpp
|
||||||
guiMainMenu.cpp
|
guiMainMenu.cpp
|
||||||
guiKeyChangeMenu.cpp
|
guiKeyChangeMenu.cpp
|
||||||
guiMessageMenu.cpp
|
guiMessageMenu.cpp
|
||||||
|
|||||||
123
src/clientlinkableobject.cpp
Normal file
123
src/clientlinkableobject.cpp
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
Copyright (C) 2012 sapier sapier at gmx dot net
|
||||||
|
|
||||||
|
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 "clientlinkableobject.h"
|
||||||
|
|
||||||
|
ClientLinkableObject::ClientLinkableObject() {
|
||||||
|
|
||||||
|
this->m_Parent = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientLinkableObject::~ClientLinkableObject() {
|
||||||
|
if (this->isLinked())
|
||||||
|
this->unlink(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ClientLinkableObject::link(ClientLinkableObject* entity) {
|
||||||
|
//TODO check if entity is already linkt (shouldn't be the case but just to be sure)
|
||||||
|
this->m_LinkedObjects.push_back(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientLinkableObject::unlink(ClientLinkableObject* entity) {
|
||||||
|
this->m_LinkedObjects.remove(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ClientLinkableObject::stepLinkedObjects(v3f pos,float dtime) {
|
||||||
|
for(std::list<ClientLinkableObject*>::iterator i = this->m_LinkedObjects.begin();
|
||||||
|
i != this->m_LinkedObjects.end(); i++) {
|
||||||
|
(*i)->setPosition(pos,dtime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClientLinkableObject::handleLinkUnlinkMessages(u8 cmd,std::istringstream* is,ClientEnvironment *m_env) {
|
||||||
|
if(cmd == AO_Message_type::Link) // Link entity
|
||||||
|
{
|
||||||
|
//Object to link entity to
|
||||||
|
u16 object_id = readU16(*is);
|
||||||
|
//offset against linked object
|
||||||
|
v3f offset = readV3F1000(*is);
|
||||||
|
|
||||||
|
ClientActiveObject* parent_cao = m_env->getActiveObject(object_id);
|
||||||
|
|
||||||
|
ClientLinkableObject* parent = dynamic_cast<ClientLinkableObject*>(parent_cao);
|
||||||
|
|
||||||
|
if (parent != NULL) {
|
||||||
|
this->linkEntity(offset,parent);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
errorstream << "Invalid object to link to!" << std::endl;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(cmd == AO_Message_type::UnLink) // UnLink entity
|
||||||
|
{
|
||||||
|
if (this->m_Parent == NULL) {
|
||||||
|
errorstream << "Unlinking object not linked!" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->unlinkEntity();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool ClientLinkableObject::linkEntity(v3f offset, ClientLinkableObject* parent) {
|
||||||
|
//already linked unlink first
|
||||||
|
if (this->m_Parent != NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO add linkchain support
|
||||||
|
if (this->m_LinkedObjects.size() > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent->link(this);
|
||||||
|
updateLinkState(true);
|
||||||
|
this->m_linkOffset = offset;
|
||||||
|
this->m_Parent = parent;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool ClientLinkableObject::unlinkEntity() {
|
||||||
|
if (this->m_Parent != NULL) {
|
||||||
|
|
||||||
|
updateLinkState(false);
|
||||||
|
this->m_Parent->unlink(this);
|
||||||
|
this->m_Parent = NULL;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClientLinkableObject::isLinked() {
|
||||||
|
if (this->m_Parent != NULL)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
65
src/clientlinkableobject.h
Normal file
65
src/clientlinkableobject.h
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
Copyright (C) 2012 sapier sapier at gmx dot net
|
||||||
|
|
||||||
|
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 CLIENTLINKABLEOBJECT_H_
|
||||||
|
#define CLIENTLINKABLEOBJECT_H_
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <sstream>
|
||||||
|
#include <irrlichttypes.h>
|
||||||
|
#include "clientobject.h"
|
||||||
|
#include "environment.h"
|
||||||
|
#include "content_object.h"
|
||||||
|
#include "utility.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
class ClientLinkableObject {
|
||||||
|
public:
|
||||||
|
ClientLinkableObject();
|
||||||
|
~ClientLinkableObject();
|
||||||
|
//internal communication between entitys NOT to be used by user
|
||||||
|
void link(ClientLinkableObject* entity);
|
||||||
|
void unlink(ClientLinkableObject* entity);
|
||||||
|
|
||||||
|
virtual void setPosition(v3f toset, float dtime) = 0;
|
||||||
|
virtual void updateLinkState(bool value) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void stepLinkedObjects(v3f pos,float dtime);
|
||||||
|
|
||||||
|
bool handleLinkUnlinkMessages(u8 cmd,std::istringstream* is,ClientEnvironment *m_env);
|
||||||
|
|
||||||
|
|
||||||
|
//user driven functions (exported by lua)
|
||||||
|
bool linkEntity(v3f offset, ClientLinkableObject* parent);
|
||||||
|
bool unlinkEntity();
|
||||||
|
|
||||||
|
bool isLinked();
|
||||||
|
v3f m_linkOffset;
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
ClientLinkableObject* m_Parent;
|
||||||
|
|
||||||
|
std::list<ClientLinkableObject*> m_LinkedObjects;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* CLIENTLINKABLEOBJECT_H_ */
|
||||||
@@ -43,8 +43,8 @@ ClientActiveObject* ClientActiveObject::create(u8 type, IGameDef *gamedef,
|
|||||||
ClientEnvironment *env)
|
ClientEnvironment *env)
|
||||||
{
|
{
|
||||||
// Find factory function
|
// Find factory function
|
||||||
core::map<u16, Factory>::Node *n;
|
core::map<u8, Factory>::Node *n;
|
||||||
n = m_types.find(type);
|
n = ClientActiveObject::getTypes().find(type);
|
||||||
if(n == NULL)
|
if(n == NULL)
|
||||||
{
|
{
|
||||||
// If factory is not found, just return.
|
// If factory is not found, just return.
|
||||||
@@ -58,13 +58,13 @@ ClientActiveObject* ClientActiveObject::create(u8 type, IGameDef *gamedef,
|
|||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientActiveObject::registerType(u16 type, Factory f)
|
void ClientActiveObject::registerType(u8 type, Factory f)
|
||||||
{
|
{
|
||||||
core::map<u16, Factory>::Node *n;
|
core::map<u8, Factory>::Node *n;
|
||||||
n = m_types.find(type);
|
n = ClientActiveObject::getTypes().find(type);
|
||||||
if(n)
|
if(n)
|
||||||
return;
|
return;
|
||||||
m_types.insert(type, f);
|
ClientActiveObject::getTypes().insert(type, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Minetest-c55
|
Minetest-c55
|
||||||
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -81,12 +81,16 @@ class ClientActiveObject : public ActiveObject
|
|||||||
protected:
|
protected:
|
||||||
// Used for creating objects based on type
|
// Used for creating objects based on type
|
||||||
typedef ClientActiveObject* (*Factory)(IGameDef *gamedef, ClientEnvironment *env);
|
typedef ClientActiveObject* (*Factory)(IGameDef *gamedef, ClientEnvironment *env);
|
||||||
static void registerType(u16 type, Factory f);
|
static void registerType(u8 type, Factory f);
|
||||||
|
|
||||||
IGameDef *m_gamedef;
|
IGameDef *m_gamedef;
|
||||||
ClientEnvironment *m_env;
|
ClientEnvironment *m_env;
|
||||||
private:
|
private:
|
||||||
// Used for creating objects based on type
|
static core::map<u8, Factory>& getTypes()
|
||||||
static core::map<u16, Factory> m_types;
|
{
|
||||||
|
static core::map<u8, Factory> types;
|
||||||
|
return types;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DistanceSortedActiveObject
|
struct DistanceSortedActiveObject
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "gamedef.h"
|
#include "gamedef.h"
|
||||||
#include "nodedef.h"
|
#include "nodedef.h"
|
||||||
#include "content_sao.h"
|
#include "content_sao.h"
|
||||||
|
#include "content_sao_rat.h"
|
||||||
|
#include "content_sao_mobv2.h"
|
||||||
|
#include "content_sao_oerkki1.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "mapblock.h" // For getNodeBlockPos
|
#include "mapblock.h" // For getNodeBlockPos
|
||||||
#include "mapgen.h" // For mapgen::make_tree
|
#include "mapgen.h" // For mapgen::make_tree
|
||||||
|
|||||||
2280
src/content_cao.cpp
2280
src/content_cao.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Minetest-c55
|
Minetest-c55
|
||||||
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -20,5 +20,104 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#ifndef CONTENT_CAO_HEADER
|
#ifndef CONTENT_CAO_HEADER
|
||||||
#define CONTENT_CAO_HEADER
|
#define CONTENT_CAO_HEADER
|
||||||
|
|
||||||
|
#include "tile.h"
|
||||||
|
#include "environment.h"
|
||||||
|
#include "settings.h"
|
||||||
|
#include <ICameraSceneNode.h>
|
||||||
|
#include <ITextSceneNode.h>
|
||||||
|
#include <IBillboardSceneNode.h>
|
||||||
|
#include "serialization.h" // For decompressZlib
|
||||||
|
#include "gamedef.h"
|
||||||
|
#include "clientobject.h"
|
||||||
|
#include "content_object.h"
|
||||||
|
#include "mesh.h"
|
||||||
|
#include "utility.h" // For IntervalLimiter
|
||||||
|
|
||||||
|
class Settings;
|
||||||
|
|
||||||
|
/*
|
||||||
|
SmoothTranslator
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct SmoothTranslator
|
||||||
|
{
|
||||||
|
v3f vect_old;
|
||||||
|
v3f vect_show;
|
||||||
|
v3f vect_aim;
|
||||||
|
f32 anim_counter;
|
||||||
|
f32 anim_time;
|
||||||
|
f32 anim_time_counter;
|
||||||
|
bool aim_is_end;
|
||||||
|
|
||||||
|
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),
|
||||||
|
aim_is_end(true)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void init(v3f vect)
|
||||||
|
{
|
||||||
|
vect_old = vect;
|
||||||
|
vect_show = vect;
|
||||||
|
vect_aim = vect;
|
||||||
|
anim_counter = 0;
|
||||||
|
anim_time = 0;
|
||||||
|
anim_time_counter = 0;
|
||||||
|
aim_is_end = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sharpen()
|
||||||
|
{
|
||||||
|
init(vect_show);
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(v3f vect_new, bool is_end_position=false, float update_interval=-1)
|
||||||
|
{
|
||||||
|
aim_is_end = is_end_position;
|
||||||
|
vect_old = vect_show;
|
||||||
|
vect_aim = vect_new;
|
||||||
|
if(update_interval > 0){
|
||||||
|
anim_time = update_interval;
|
||||||
|
} else {
|
||||||
|
if(anim_time < 0.001 || anim_time > 1.0)
|
||||||
|
anim_time = anim_time_counter;
|
||||||
|
else
|
||||||
|
anim_time = anim_time * 0.9 + anim_time_counter * 0.1;
|
||||||
|
}
|
||||||
|
anim_time_counter = 0;
|
||||||
|
anim_counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void translate(f32 dtime)
|
||||||
|
{
|
||||||
|
anim_time_counter = anim_time_counter + dtime;
|
||||||
|
anim_counter = anim_counter + dtime;
|
||||||
|
v3f vect_move = vect_aim - vect_old;
|
||||||
|
f32 moveratio = 1.0;
|
||||||
|
if(anim_time > 0.001)
|
||||||
|
moveratio = anim_time_counter / anim_time;
|
||||||
|
// Move a bit less than should, to avoid oscillation
|
||||||
|
moveratio = moveratio * 0.8;
|
||||||
|
float move_end = 1.5;
|
||||||
|
if(aim_is_end)
|
||||||
|
move_end = 1.0;
|
||||||
|
if(moveratio > move_end)
|
||||||
|
moveratio = move_end;
|
||||||
|
vect_show = vect_old + vect_move * moveratio;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_moving()
|
||||||
|
{
|
||||||
|
return ((anim_time_counter / anim_time) < 1.4);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void setBillboardTextureMatrix(scene::IBillboardSceneNode *bill,
|
||||||
|
float txs, float tys, int col, int row);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
181
src/content_cao_firefly.cpp
Normal file
181
src/content_cao_firefly.cpp
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2012 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_cao.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
FireflyCAO
|
||||||
|
*/
|
||||||
|
class FireflyCAO : public ClientActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FireflyCAO(IGameDef *gamedef, ClientEnvironment *env):
|
||||||
|
ClientActiveObject(0, gamedef, env),
|
||||||
|
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
|
||||||
|
m_node(NULL),
|
||||||
|
m_position(v3f(0,10*BS,0)),
|
||||||
|
m_yaw(0)
|
||||||
|
{
|
||||||
|
registerType(getType(), create);
|
||||||
|
};
|
||||||
|
|
||||||
|
~FireflyCAO()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u8 getType() const { return ACTIVEOBJECT_TYPE_FIREFLY; }
|
||||||
|
|
||||||
|
static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
|
||||||
|
{
|
||||||
|
return new FireflyCAO(gamedef, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||||
|
IrrlichtDevice *irr)
|
||||||
|
{
|
||||||
|
if(m_node != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//video::IVideoDriver* driver = smgr->getVideoDriver();
|
||||||
|
scene::SMesh *mesh = new scene::SMesh();
|
||||||
|
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||||
|
video::SColor c(255,255,255,255);
|
||||||
|
video::S3DVertex vertices[4] =
|
||||||
|
{
|
||||||
|
video::S3DVertex(0,0,0, 0,0,0, c, 0,1),
|
||||||
|
video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
|
||||||
|
video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
|
||||||
|
video::S3DVertex(0,BS/2,0, 0,0,0, c, 0,0),
|
||||||
|
};
|
||||||
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
|
buf->append(vertices, 4, indices, 6);
|
||||||
|
// Set material
|
||||||
|
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||||
|
//buf->getMaterial().setTexture(0, NULL);
|
||||||
|
buf->getMaterial().setTexture(0, tsrc->getTextureRaw("firefly.png"));
|
||||||
|
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
|
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||||
|
// Add to mesh
|
||||||
|
mesh->addMeshBuffer(buf);
|
||||||
|
buf->drop();
|
||||||
|
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
||||||
|
mesh->drop();
|
||||||
|
// Set it to use the materials of the meshbuffers directly.
|
||||||
|
// This is needed for changing the texture in the future
|
||||||
|
m_node->setReadOnlyMaterials(true);
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeFromScene()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node->remove();
|
||||||
|
m_node = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateLight(u8 light_at_pos)
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u8 li = 255;
|
||||||
|
video::SColor color(255,li,li,li);
|
||||||
|
setMeshColor(m_node->getMesh(), color);
|
||||||
|
}
|
||||||
|
|
||||||
|
v3s16 getLightPosition()
|
||||||
|
{
|
||||||
|
return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateNodePos()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//m_node->setPosition(m_position);
|
||||||
|
m_node->setPosition(pos_translator.vect_show);
|
||||||
|
|
||||||
|
v3f rot = m_node->getRotation();
|
||||||
|
rot.Y = 180.0 - m_yaw;
|
||||||
|
m_node->setRotation(rot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void step(float dtime, ClientEnvironment *env)
|
||||||
|
{
|
||||||
|
pos_translator.translate(dtime);
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void processMessage(const std::string &data)
|
||||||
|
{
|
||||||
|
//infostream<<"FireflyCAO: Got message"<<std::endl;
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// command
|
||||||
|
u8 cmd = readU8(is);
|
||||||
|
if(cmd == AO_Message_type::SetPosition)
|
||||||
|
{
|
||||||
|
// pos
|
||||||
|
m_position = readV3F1000(is);
|
||||||
|
pos_translator.update(m_position);
|
||||||
|
// yaw
|
||||||
|
m_yaw = readF1000(is);
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize(const std::string &data)
|
||||||
|
{
|
||||||
|
//infostream<<"FireflyCAO: Got init data"<<std::endl;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// version
|
||||||
|
u8 version = readU8(is);
|
||||||
|
// check version
|
||||||
|
if(version != 0)
|
||||||
|
return;
|
||||||
|
// pos
|
||||||
|
m_position = readV3F1000(is);
|
||||||
|
pos_translator.init(m_position);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
core::aabbox3d<f32>* getSelectionBox()
|
||||||
|
{return &m_selection_box;}
|
||||||
|
|
||||||
|
v3f getPosition()
|
||||||
|
{return m_position;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
core::aabbox3d<f32> m_selection_box;
|
||||||
|
scene::IMeshSceneNode *m_node;
|
||||||
|
v3f m_position;
|
||||||
|
float m_yaw;
|
||||||
|
SmoothTranslator pos_translator;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
FireflyCAO proto_FireflyCAO(NULL, NULL);
|
||||||
|
|
||||||
239
src/content_cao_item.cpp
Normal file
239
src/content_cao_item.cpp
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2012 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_cao.h"
|
||||||
|
#include "inventory.h"
|
||||||
|
/*
|
||||||
|
ItemCAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ItemCAO : public ClientActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ItemCAO(IGameDef *gamedef, ClientEnvironment *env):
|
||||||
|
ClientActiveObject(0, gamedef, env),
|
||||||
|
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.),
|
||||||
|
m_node(NULL),
|
||||||
|
m_position(v3f(0,10*BS,0))
|
||||||
|
{
|
||||||
|
if(!gamedef && !env)
|
||||||
|
{
|
||||||
|
ClientActiveObject::registerType(getType(), create);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~ItemCAO()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u8 getType() const
|
||||||
|
{ return ACTIVEOBJECT_TYPE_ITEM; }
|
||||||
|
|
||||||
|
static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
|
||||||
|
{
|
||||||
|
return new ItemCAO(gamedef, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||||
|
IrrlichtDevice *irr)
|
||||||
|
{
|
||||||
|
if(m_node != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//video::IVideoDriver* driver = smgr->getVideoDriver();
|
||||||
|
|
||||||
|
scene::SMesh *mesh = new scene::SMesh();
|
||||||
|
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||||
|
video::SColor c(255,255,255,255);
|
||||||
|
video::S3DVertex vertices[4] =
|
||||||
|
{
|
||||||
|
/*video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
|
||||||
|
video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
|
||||||
|
video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
|
||||||
|
video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),*/
|
||||||
|
video::S3DVertex(BS/3.,0,0, 0,0,0, c, 0,1),
|
||||||
|
video::S3DVertex(-BS/3.,0,0, 0,0,0, c, 1,1),
|
||||||
|
video::S3DVertex(-BS/3.,0+BS*2./3.,0, 0,0,0, c, 1,0),
|
||||||
|
video::S3DVertex(BS/3.,0+BS*2./3.,0, 0,0,0, c, 0,0),
|
||||||
|
};
|
||||||
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
|
buf->append(vertices, 4, indices, 6);
|
||||||
|
// Set material
|
||||||
|
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||||
|
// Initialize with a generated placeholder texture
|
||||||
|
buf->getMaterial().setTexture(0, tsrc->getTextureRaw(""));
|
||||||
|
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
|
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||||
|
// Add to mesh
|
||||||
|
mesh->addMeshBuffer(buf);
|
||||||
|
buf->drop();
|
||||||
|
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
||||||
|
mesh->drop();
|
||||||
|
// Set it to use the materials of the meshbuffers directly.
|
||||||
|
// This is needed for changing the texture in the future
|
||||||
|
m_node->setReadOnlyMaterials(true);
|
||||||
|
updateNodePos();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Update image of node
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Create an inventory item to see what is its image
|
||||||
|
std::istringstream is(m_inventorystring, std::ios_base::binary);
|
||||||
|
video::ITexture *texture = NULL;
|
||||||
|
try{
|
||||||
|
InventoryItem *item = NULL;
|
||||||
|
item = InventoryItem::deSerialize(is, m_gamedef);
|
||||||
|
infostream<<__FUNCTION_NAME<<": m_inventorystring=\""
|
||||||
|
<<m_inventorystring<<"\" -> item="<<item
|
||||||
|
<<std::endl;
|
||||||
|
if(item)
|
||||||
|
{
|
||||||
|
texture = item->getImage();
|
||||||
|
delete item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(SerializationError &e)
|
||||||
|
{
|
||||||
|
infostream<<"WARNING: "<<__FUNCTION_NAME
|
||||||
|
<<": error deSerializing inventorystring \""
|
||||||
|
<<m_inventorystring<<"\""<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set meshbuffer texture
|
||||||
|
buf->getMaterial().setTexture(0, texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeFromScene()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node->remove();
|
||||||
|
m_node = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateLight(u8 light_at_pos)
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u8 li = decode_light(light_at_pos);
|
||||||
|
video::SColor color(255,li,li,li);
|
||||||
|
setMeshColor(m_node->getMesh(), color);
|
||||||
|
}
|
||||||
|
|
||||||
|
v3s16 getLightPosition()
|
||||||
|
{
|
||||||
|
return floatToInt(m_position, BS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateNodePos()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node->setPosition(m_position);
|
||||||
|
}
|
||||||
|
|
||||||
|
void step(float dtime, ClientEnvironment *env)
|
||||||
|
{
|
||||||
|
if(m_node)
|
||||||
|
{
|
||||||
|
/*v3f rot = m_node->getRotation();
|
||||||
|
rot.Y += dtime * 120;
|
||||||
|
m_node->setRotation(rot);*/
|
||||||
|
LocalPlayer *player = env->getLocalPlayer();
|
||||||
|
assert(player);
|
||||||
|
v3f rot = m_node->getRotation();
|
||||||
|
rot.Y = 180.0 - (player->getYaw());
|
||||||
|
m_node->setRotation(rot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void processMessage(const std::string &data)
|
||||||
|
{
|
||||||
|
//infostream<<"ItemCAO: Got message"<<std::endl;
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// command
|
||||||
|
u8 cmd = readU8(is);
|
||||||
|
if(cmd == AO_Message_type::SetPosition)
|
||||||
|
{
|
||||||
|
// pos
|
||||||
|
m_position = readV3F1000(is);
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize(const std::string &data)
|
||||||
|
{
|
||||||
|
infostream<<"ItemCAO: Got init data"<<std::endl;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// version
|
||||||
|
u8 version = readU8(is);
|
||||||
|
// check version
|
||||||
|
if(version != 0)
|
||||||
|
return;
|
||||||
|
// pos
|
||||||
|
m_position = readV3F1000(is);
|
||||||
|
// inventorystring
|
||||||
|
m_inventorystring = deSerializeString(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateNodePos();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Set infotext to item name if item cannot be deserialized
|
||||||
|
*/
|
||||||
|
try{
|
||||||
|
InventoryItem *item = NULL;
|
||||||
|
item = InventoryItem::deSerialize(m_inventorystring, m_gamedef);
|
||||||
|
if(item){
|
||||||
|
if(!item->isKnown())
|
||||||
|
m_infotext = "Unknown item: '" + m_inventorystring + "'";
|
||||||
|
}
|
||||||
|
delete item;
|
||||||
|
}
|
||||||
|
catch(SerializationError &e)
|
||||||
|
{
|
||||||
|
m_infotext = "Unknown item: '" + m_inventorystring + "'";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
core::aabbox3d<f32>* getSelectionBox()
|
||||||
|
{return &m_selection_box;}
|
||||||
|
v3f getPosition()
|
||||||
|
{return m_position;}
|
||||||
|
|
||||||
|
std::string infoText()
|
||||||
|
{return m_infotext;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
core::aabbox3d<f32> m_selection_box;
|
||||||
|
scene::IMeshSceneNode *m_node;
|
||||||
|
v3f m_position;
|
||||||
|
std::string m_inventorystring;
|
||||||
|
std::string m_infotext;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
ItemCAO proto_ItemCAO(NULL, NULL);
|
||||||
426
src/content_cao_lua.cpp
Normal file
426
src/content_cao_lua.cpp
Normal file
@@ -0,0 +1,426 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2012 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 <list>
|
||||||
|
#include "content_cao.h"
|
||||||
|
#include "luaentity_common.h"
|
||||||
|
#include "clientlinkableobject.h"
|
||||||
|
|
||||||
|
class LuaEntityCAO : public ClientActiveObject, public ClientLinkableObject
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
core::aabbox3d<f32> m_selection_box;
|
||||||
|
scene::IMeshSceneNode *m_meshnode;
|
||||||
|
scene::IBillboardSceneNode *m_spritenode;
|
||||||
|
v3f m_position;
|
||||||
|
v3f m_velocity;
|
||||||
|
v3f m_acceleration;
|
||||||
|
float m_yaw;
|
||||||
|
struct LuaEntityProperties *m_prop;
|
||||||
|
SmoothTranslator pos_translator;
|
||||||
|
// Spritesheet/animation stuff
|
||||||
|
v2f m_tx_size;
|
||||||
|
v2s16 m_tx_basepos;
|
||||||
|
bool m_tx_select_horiz_by_yawpitch;
|
||||||
|
int m_anim_frame;
|
||||||
|
int m_anim_num_frames;
|
||||||
|
float m_anim_framelength;
|
||||||
|
float m_anim_timer;
|
||||||
|
public:
|
||||||
|
|
||||||
|
inline u8 getType() const { return ACTIVEOBJECT_TYPE_LUAENTITY; }
|
||||||
|
|
||||||
|
inline core::aabbox3d<f32>* getSelectionBox()
|
||||||
|
{ return &m_selection_box; }
|
||||||
|
|
||||||
|
inline v3f getPosition()
|
||||||
|
{ return pos_translator.vect_show; }
|
||||||
|
|
||||||
|
LuaEntityCAO(IGameDef *gamedef, ClientEnvironment *env):
|
||||||
|
ClientActiveObject(0, gamedef, env),
|
||||||
|
m_selection_box(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.),
|
||||||
|
m_meshnode(NULL),
|
||||||
|
m_spritenode(NULL),
|
||||||
|
m_position(v3f(0,10*BS,0)),
|
||||||
|
m_velocity(v3f(0,0,0)),
|
||||||
|
m_acceleration(v3f(0,0,0)),
|
||||||
|
m_yaw(0),
|
||||||
|
m_prop(new LuaEntityProperties),
|
||||||
|
m_tx_size(1,1),
|
||||||
|
m_tx_basepos(0,0),
|
||||||
|
m_tx_select_horiz_by_yawpitch(false),
|
||||||
|
m_anim_frame(0),
|
||||||
|
m_anim_num_frames(1),
|
||||||
|
m_anim_framelength(0.2),
|
||||||
|
m_anim_timer(0)
|
||||||
|
{
|
||||||
|
if(gamedef == NULL)
|
||||||
|
ClientActiveObject::registerType(LuaEntityCAO::getType(), LuaEntityCAO::create);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize(const std::string &data)
|
||||||
|
{
|
||||||
|
infostream<<"LuaEntityCAO: Got init data"<<std::endl;
|
||||||
|
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// version
|
||||||
|
u8 version = readU8(is);
|
||||||
|
// check version
|
||||||
|
if(version != 0)
|
||||||
|
return;
|
||||||
|
// pos
|
||||||
|
m_position = readV3F1000(is);
|
||||||
|
// yaw
|
||||||
|
m_yaw = readF1000(is);
|
||||||
|
// properties
|
||||||
|
std::istringstream prop_is(deSerializeLongString(is), std::ios::binary);
|
||||||
|
m_prop->deSerialize(prop_is);
|
||||||
|
|
||||||
|
infostream<<"m_prop: "<<m_prop->dump()<<std::endl;
|
||||||
|
|
||||||
|
m_selection_box = m_prop->collisionbox;
|
||||||
|
m_selection_box.MinEdge *= BS;
|
||||||
|
m_selection_box.MaxEdge *= BS;
|
||||||
|
|
||||||
|
pos_translator.init(m_position);
|
||||||
|
|
||||||
|
m_tx_size.X = 1.0 / m_prop->spritediv.X;
|
||||||
|
m_tx_size.Y = 1.0 / m_prop->spritediv.Y;
|
||||||
|
m_tx_basepos.X = m_tx_size.X * m_prop->initial_sprite_basepos.X;
|
||||||
|
m_tx_basepos.Y = m_tx_size.Y * m_prop->initial_sprite_basepos.Y;
|
||||||
|
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
~LuaEntityCAO()
|
||||||
|
{
|
||||||
|
delete m_prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
|
||||||
|
{
|
||||||
|
return new LuaEntityCAO(gamedef, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||||
|
IrrlichtDevice *irr)
|
||||||
|
{
|
||||||
|
if(m_meshnode != NULL || m_spritenode != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//video::IVideoDriver* driver = smgr->getVideoDriver();
|
||||||
|
|
||||||
|
if(m_prop->visual == "sprite"){
|
||||||
|
infostream<<"LuaEntityCAO::addToScene(): single_sprite"<<std::endl;
|
||||||
|
m_spritenode = smgr->addBillboardSceneNode(
|
||||||
|
NULL, v2f(1, 1), v3f(0,0,0), -1);
|
||||||
|
m_spritenode->setMaterialTexture(0,
|
||||||
|
tsrc->getTextureRaw("unknown_block.png"));
|
||||||
|
m_spritenode->setMaterialFlag(video::EMF_LIGHTING, false);
|
||||||
|
m_spritenode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
m_spritenode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
|
||||||
|
m_spritenode->setMaterialFlag(video::EMF_FOG_ENABLE, true);
|
||||||
|
m_spritenode->setColor(video::SColor(255,0,0,0));
|
||||||
|
m_spritenode->setVisible(false); /* Set visible when brightness is known */
|
||||||
|
m_spritenode->setSize(m_prop->visual_size*BS);
|
||||||
|
{
|
||||||
|
const float txs = 1.0 / 1;
|
||||||
|
const float tys = 1.0 / 1;
|
||||||
|
setBillboardTextureMatrix(m_spritenode,
|
||||||
|
txs, tys, 0, 0);
|
||||||
|
}
|
||||||
|
} else if(m_prop->visual == "cube"){
|
||||||
|
infostream<<"LuaEntityCAO::addToScene(): cube"<<std::endl;
|
||||||
|
scene::IMesh *mesh = createCubeMesh(v3f(BS,BS,BS));
|
||||||
|
m_meshnode = smgr->addMeshSceneNode(mesh, NULL);
|
||||||
|
mesh->drop();
|
||||||
|
|
||||||
|
m_meshnode->setScale(v3f(1));
|
||||||
|
// Will be shown when we know the brightness
|
||||||
|
m_meshnode->setVisible(false);
|
||||||
|
} else if (m_prop->visual == "plant") {
|
||||||
|
infostream<<"LuaEntityCAO::addToScene(): plant"<<std::endl;
|
||||||
|
scene::IMesh *mesh = createPlantMesh(v3f(BS,BS,BS));
|
||||||
|
m_meshnode = smgr->addMeshSceneNode(mesh, NULL);
|
||||||
|
mesh->drop();
|
||||||
|
|
||||||
|
m_meshnode->setScale(v3f(1));
|
||||||
|
// Will be shown when we know the brightness
|
||||||
|
m_meshnode->setVisible(false);
|
||||||
|
} else if (m_prop->visual == "cube_disorted") {
|
||||||
|
infostream<<"LuaEntityCAO::addToScene(): irregular_cube"<<std::endl;
|
||||||
|
scene::IMesh *mesh = createCubeMesh(v3f(BS,BS,BS), m_prop->collisionbox);
|
||||||
|
m_meshnode = smgr->addMeshSceneNode(mesh, NULL);
|
||||||
|
mesh->drop();
|
||||||
|
|
||||||
|
m_meshnode->setScale(v3f(1));
|
||||||
|
// Will be shown when we know the brightness
|
||||||
|
m_meshnode->setVisible(false);
|
||||||
|
} else {
|
||||||
|
infostream<<"LuaEntityCAO::addToScene(): \""<<m_prop->visual
|
||||||
|
<<"\" not supported"<<std::endl;
|
||||||
|
}
|
||||||
|
updateTextures("");
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeFromScene()
|
||||||
|
{
|
||||||
|
if(m_meshnode){
|
||||||
|
m_meshnode->remove();
|
||||||
|
m_meshnode = NULL;
|
||||||
|
}
|
||||||
|
if(m_spritenode){
|
||||||
|
m_spritenode->remove();
|
||||||
|
m_spritenode = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateLight(u8 light_at_pos)
|
||||||
|
{
|
||||||
|
u8 li = decode_light(light_at_pos);
|
||||||
|
video::SColor color(255,li,li,li);
|
||||||
|
if(m_meshnode){
|
||||||
|
setMeshColor(m_meshnode->getMesh(), color);
|
||||||
|
m_meshnode->setVisible(true);
|
||||||
|
}
|
||||||
|
if(m_spritenode){
|
||||||
|
m_spritenode->setColor(color);
|
||||||
|
m_spritenode->setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v3s16 getLightPosition()
|
||||||
|
{
|
||||||
|
return floatToInt(m_position, BS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateNodePos()
|
||||||
|
{
|
||||||
|
if(m_meshnode){
|
||||||
|
m_meshnode->setPosition(pos_translator.vect_show);
|
||||||
|
}
|
||||||
|
if(m_spritenode){
|
||||||
|
m_spritenode->setPosition(pos_translator.vect_show);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void step(float dtime, ClientEnvironment *env)
|
||||||
|
{
|
||||||
|
//if liked movement is handled by parent entity
|
||||||
|
if(!this->isLinked()) {
|
||||||
|
if(m_prop->physical){
|
||||||
|
core::aabbox3d<f32> box = m_prop->collisionbox;
|
||||||
|
box.MinEdge *= BS;
|
||||||
|
box.MaxEdge *= BS;
|
||||||
|
collisionMoveResult moveresult;
|
||||||
|
f32 pos_max_d = BS*0.25; // Distance per iteration
|
||||||
|
v3f p_pos = m_position;
|
||||||
|
v3f p_velocity = m_velocity;
|
||||||
|
IGameDef *gamedef = env->getGameDef();
|
||||||
|
moveresult = collisionMovePrecise(&env->getMap(), gamedef,
|
||||||
|
pos_max_d, box, dtime, p_pos, p_velocity);
|
||||||
|
// Apply results
|
||||||
|
m_position = p_pos;
|
||||||
|
m_velocity = p_velocity;
|
||||||
|
|
||||||
|
bool is_end_position = moveresult.collides;
|
||||||
|
pos_translator.update(m_position, is_end_position, dtime);
|
||||||
|
pos_translator.translate(dtime);
|
||||||
|
updateNodePos();
|
||||||
|
|
||||||
|
m_velocity += dtime * m_acceleration;
|
||||||
|
} else {
|
||||||
|
m_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration;
|
||||||
|
m_velocity += dtime * m_acceleration;
|
||||||
|
pos_translator.update(m_position, pos_translator.aim_is_end, pos_translator.anim_time);
|
||||||
|
pos_translator.translate(dtime);
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stepLinkedObjects(this->m_position,dtime);
|
||||||
|
|
||||||
|
m_anim_timer += dtime;
|
||||||
|
if(m_anim_timer >= m_anim_framelength){
|
||||||
|
m_anim_timer -= m_anim_framelength;
|
||||||
|
m_anim_frame++;
|
||||||
|
if(m_anim_frame >= m_anim_num_frames)
|
||||||
|
m_anim_frame = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTexturePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateTexturePos()
|
||||||
|
{
|
||||||
|
if(m_spritenode){
|
||||||
|
scene::ICameraSceneNode* camera =
|
||||||
|
m_spritenode->getSceneManager()->getActiveCamera();
|
||||||
|
if(!camera)
|
||||||
|
return;
|
||||||
|
v3f cam_to_entity = m_spritenode->getAbsolutePosition()
|
||||||
|
- camera->getAbsolutePosition();
|
||||||
|
cam_to_entity.normalize();
|
||||||
|
|
||||||
|
int row = m_tx_basepos.Y;
|
||||||
|
int col = m_tx_basepos.X;
|
||||||
|
|
||||||
|
if(m_tx_select_horiz_by_yawpitch)
|
||||||
|
{
|
||||||
|
if(cam_to_entity.Y > 0.75)
|
||||||
|
col += 5;
|
||||||
|
else if(cam_to_entity.Y < -0.75)
|
||||||
|
col += 4;
|
||||||
|
else{
|
||||||
|
float mob_dir = atan2(cam_to_entity.Z, cam_to_entity.X) / PI * 180.;
|
||||||
|
float dir = mob_dir - m_yaw;
|
||||||
|
dir = wrapDegrees_180(dir);
|
||||||
|
//infostream<<"id="<<m_id<<" dir="<<dir<<std::endl;
|
||||||
|
if(fabs(wrapDegrees_180(dir - 0)) <= 45.1)
|
||||||
|
col += 2;
|
||||||
|
else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1)
|
||||||
|
col += 3;
|
||||||
|
else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1)
|
||||||
|
col += 0;
|
||||||
|
else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1)
|
||||||
|
col += 1;
|
||||||
|
else
|
||||||
|
col += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Animation goes downwards
|
||||||
|
row += m_anim_frame;
|
||||||
|
|
||||||
|
float txs = m_tx_size.X;
|
||||||
|
float tys = m_tx_size.Y;
|
||||||
|
setBillboardTextureMatrix(m_spritenode,
|
||||||
|
txs, tys, col, row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateTextures(const std::string &mod)
|
||||||
|
{
|
||||||
|
ITextureSource *tsrc = m_gamedef->tsrc();
|
||||||
|
|
||||||
|
if(m_spritenode){
|
||||||
|
std::string texturestring = "unknown_block.png";
|
||||||
|
if(m_prop->textures.size() >= 1)
|
||||||
|
texturestring = m_prop->textures[0];
|
||||||
|
texturestring += mod;
|
||||||
|
m_spritenode->setMaterialTexture(0,
|
||||||
|
tsrc->getTextureRaw(texturestring));
|
||||||
|
}
|
||||||
|
if(m_meshnode){
|
||||||
|
for (u32 i = 0; i < 6; ++i)
|
||||||
|
{
|
||||||
|
std::string texturestring = "unknown_block.png";
|
||||||
|
if(m_prop->textures.size() > i)
|
||||||
|
texturestring = m_prop->textures[i];
|
||||||
|
texturestring += mod;
|
||||||
|
AtlasPointer ap = tsrc->getTexture(texturestring);
|
||||||
|
|
||||||
|
// Get the tile texture and atlas transformation
|
||||||
|
video::ITexture* atlas = ap.atlas;
|
||||||
|
v2f pos = ap.pos;
|
||||||
|
v2f size = ap.size;
|
||||||
|
|
||||||
|
// Set material flags and texture
|
||||||
|
video::SMaterial& material = m_meshnode->getMaterial(i);
|
||||||
|
material.setFlag(video::EMF_LIGHTING, false);
|
||||||
|
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
material.setTexture(0, atlas);
|
||||||
|
material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
|
||||||
|
material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void processMessage(const std::string &data)
|
||||||
|
{
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// command
|
||||||
|
u8 cmd = readU8(is);
|
||||||
|
if(cmd == AO_Message_type::SetPosition) // update position
|
||||||
|
{
|
||||||
|
// do_interpolate
|
||||||
|
bool do_interpolate = readU8(is);
|
||||||
|
// pos
|
||||||
|
m_position = readV3F1000(is);
|
||||||
|
// velocity
|
||||||
|
m_velocity = readV3F1000(is);
|
||||||
|
// acceleration
|
||||||
|
m_acceleration = readV3F1000(is);
|
||||||
|
// yaw
|
||||||
|
m_yaw = readF1000(is);
|
||||||
|
// is_end_position (for interpolation)
|
||||||
|
bool is_end_position = readU8(is);
|
||||||
|
// update_interval
|
||||||
|
float update_interval = readF1000(is);
|
||||||
|
|
||||||
|
if(do_interpolate){
|
||||||
|
if(!m_prop->physical)
|
||||||
|
pos_translator.update(m_position, is_end_position, update_interval);
|
||||||
|
} else {
|
||||||
|
pos_translator.init(m_position);
|
||||||
|
}
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
else if(cmd == AO_Message_type::SetTextureMod) // set texture modification
|
||||||
|
{
|
||||||
|
std::string mod = deSerializeString(is);
|
||||||
|
updateTextures(mod);
|
||||||
|
}
|
||||||
|
else if(cmd == AO_Message_type::SetSprite) // set sprite
|
||||||
|
{
|
||||||
|
v2s16 p = readV2S16(is);
|
||||||
|
int num_frames = readU16(is);
|
||||||
|
float framelength = readF1000(is);
|
||||||
|
bool select_horiz_by_yawpitch = readU8(is);
|
||||||
|
|
||||||
|
m_tx_basepos = p;
|
||||||
|
m_anim_num_frames = num_frames;
|
||||||
|
m_anim_framelength = framelength;
|
||||||
|
m_tx_select_horiz_by_yawpitch = select_horiz_by_yawpitch;
|
||||||
|
|
||||||
|
updateTexturePos();
|
||||||
|
}
|
||||||
|
else if (handleLinkUnlinkMessages(cmd,&is,this->m_env))
|
||||||
|
{
|
||||||
|
//Link unlink already done in handleLinkUnlinkMessages!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPosition(v3f toset, float dtime){
|
||||||
|
if (this->isLinked()) {
|
||||||
|
this->m_position = toset + this->m_linkOffset;
|
||||||
|
|
||||||
|
pos_translator.update(m_position, pos_translator.aim_is_end, pos_translator.anim_time);
|
||||||
|
pos_translator.translate(dtime);
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateLinkState(bool value) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
LuaEntityCAO proto_LuaEntityCAO(NULL, NULL);
|
||||||
464
src/content_cao_mobv2.cpp
Normal file
464
src/content_cao_mobv2.cpp
Normal file
@@ -0,0 +1,464 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2012 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_cao.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
MobV2CAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
class MobV2CAO : public ClientActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
MobV2CAO(IGameDef *gamedef, ClientEnvironment *env):
|
||||||
|
ClientActiveObject(0, gamedef, env),
|
||||||
|
m_selection_box(-0.4*BS,-0.4*BS,-0.4*BS, 0.4*BS,0.8*BS,0.4*BS),
|
||||||
|
m_node(NULL),
|
||||||
|
m_position(v3f(0,10*BS,0)),
|
||||||
|
m_yaw(0),
|
||||||
|
m_walking(false),
|
||||||
|
m_walking_unset_timer(0),
|
||||||
|
m_walk_timer(0),
|
||||||
|
m_walk_frame(0),
|
||||||
|
m_damage_visual_timer(0),
|
||||||
|
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);
|
||||||
|
|
||||||
|
m_properties = new Settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
~MobV2CAO()
|
||||||
|
{
|
||||||
|
delete m_properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u8 getType() const { return ACTIVEOBJECT_TYPE_MOBV2; }
|
||||||
|
|
||||||
|
static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
|
||||||
|
{
|
||||||
|
return new MobV2CAO(gamedef, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||||
|
IrrlichtDevice *irr)
|
||||||
|
{
|
||||||
|
if(m_node != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*infostream<<"MobV2CAO::addToScene using texture_name="<<
|
||||||
|
m_texture_name<<std::endl;*/
|
||||||
|
std::string texture_string = m_texture_name +
|
||||||
|
"^[makealpha:128,0,0^[makealpha:128,128,0";
|
||||||
|
|
||||||
|
scene::IBillboardSceneNode *bill = smgr->addBillboardSceneNode(
|
||||||
|
NULL, v2f(1, 1), v3f(0,0,0), -1);
|
||||||
|
bill->setMaterialTexture(0, tsrc->getTextureRaw(texture_string));
|
||||||
|
bill->setMaterialFlag(video::EMF_LIGHTING, false);
|
||||||
|
bill->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
bill->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
|
||||||
|
bill->setMaterialFlag(video::EMF_FOG_ENABLE, true);
|
||||||
|
bill->setColor(video::SColor(255,0,0,0));
|
||||||
|
bill->setVisible(false); /* Set visible when brightness is known */
|
||||||
|
bill->setSize(m_sprite_size);
|
||||||
|
if(m_sprite_type == "humanoid_1"){
|
||||||
|
const float txp = 1./192;
|
||||||
|
const float txs = txp*32;
|
||||||
|
const float typ = 1./240;
|
||||||
|
const float tys = typ*48;
|
||||||
|
setBillboardTextureMatrix(bill, txs, tys, 0, 0);
|
||||||
|
} else if(m_sprite_type == "simple"){
|
||||||
|
const float txs = 1.0;
|
||||||
|
const float tys = 1.0 / m_simple_anim_frames;
|
||||||
|
setBillboardTextureMatrix(bill, txs, tys, 0, 0);
|
||||||
|
} else {
|
||||||
|
infostream<<"MobV2CAO: Unknown sprite type \""<<m_sprite_type<<"\""
|
||||||
|
<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node = bill;
|
||||||
|
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeFromScene()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node->remove();
|
||||||
|
m_node = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateLight(u8 light_at_pos)
|
||||||
|
{
|
||||||
|
if(m_lock_full_brightness)
|
||||||
|
light_at_pos = 15;
|
||||||
|
|
||||||
|
m_last_light = light_at_pos;
|
||||||
|
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(m_damage_visual_timer > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(m_shooting && m_bright_shooting)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*if(light_at_pos <= 2){
|
||||||
|
m_node->setVisible(false);
|
||||||
|
return;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
m_node->setVisible(true);
|
||||||
|
|
||||||
|
u8 li = decode_light(light_at_pos);
|
||||||
|
video::SColor color(255,li,li,li);
|
||||||
|
m_node->setColor(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
v3s16 getLightPosition()
|
||||||
|
{
|
||||||
|
return floatToInt(m_position+v3f(0,0,0), BS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateNodePos()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node->setPosition(pos_translator.vect_show + v3f(0,m_sprite_y,0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void step(float dtime, ClientEnvironment *env)
|
||||||
|
{
|
||||||
|
scene::IBillboardSceneNode *bill = m_node;
|
||||||
|
if(!bill)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pos_translator.translate(dtime);
|
||||||
|
|
||||||
|
if(m_sprite_type == "humanoid_1"){
|
||||||
|
scene::ICameraSceneNode* camera = m_node->getSceneManager()->getActiveCamera();
|
||||||
|
if(!camera)
|
||||||
|
return;
|
||||||
|
v3f cam_to_mob = m_node->getAbsolutePosition() - camera->getAbsolutePosition();
|
||||||
|
cam_to_mob.normalize();
|
||||||
|
int col = 0;
|
||||||
|
if(cam_to_mob.Y > 0.75)
|
||||||
|
col = 5;
|
||||||
|
else if(cam_to_mob.Y < -0.75)
|
||||||
|
col = 4;
|
||||||
|
else{
|
||||||
|
float mob_dir = atan2(cam_to_mob.Z, cam_to_mob.X) / PI * 180.;
|
||||||
|
float dir = mob_dir - m_yaw;
|
||||||
|
dir = wrapDegrees_180(dir);
|
||||||
|
//infostream<<"id="<<m_id<<" dir="<<dir<<std::endl;
|
||||||
|
if(fabs(wrapDegrees_180(dir - 0)) <= 45.1)
|
||||||
|
col = 2;
|
||||||
|
else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1)
|
||||||
|
col = 3;
|
||||||
|
else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1)
|
||||||
|
col = 0;
|
||||||
|
else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1)
|
||||||
|
col = 1;
|
||||||
|
else
|
||||||
|
col = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
int row = 0;
|
||||||
|
if(m_shooting){
|
||||||
|
row = 3;
|
||||||
|
} else if(m_walking){
|
||||||
|
m_walk_timer += dtime;
|
||||||
|
if(m_walk_timer >= 0.5){
|
||||||
|
m_walk_frame = (m_walk_frame + 1) % 2;
|
||||||
|
m_walk_timer = 0;
|
||||||
|
}
|
||||||
|
if(m_walk_frame == 0)
|
||||||
|
row = 1;
|
||||||
|
else
|
||||||
|
row = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float txp = 1./192;
|
||||||
|
const float txs = txp*32;
|
||||||
|
const float typ = 1./240;
|
||||||
|
const float tys = typ*48;
|
||||||
|
setBillboardTextureMatrix(bill, txs, tys, col, row);
|
||||||
|
} else if(m_sprite_type == "simple"){
|
||||||
|
m_walk_timer += dtime;
|
||||||
|
if(m_walk_timer >= m_simple_anim_frametime){
|
||||||
|
m_walk_frame = (m_walk_frame + 1) % m_simple_anim_frames;
|
||||||
|
m_walk_timer = 0;
|
||||||
|
}
|
||||||
|
int col = 0;
|
||||||
|
int row = m_walk_frame;
|
||||||
|
const float txs = 1.0;
|
||||||
|
const float tys = 1.0 / m_simple_anim_frames;
|
||||||
|
setBillboardTextureMatrix(bill, txs, tys, col, row);
|
||||||
|
} else {
|
||||||
|
infostream<<"MobV2CAO::step(): Unknown sprite type \""
|
||||||
|
<<m_sprite_type<<"\""<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateNodePos();
|
||||||
|
|
||||||
|
/* Damage local player */
|
||||||
|
if(m_player_hit_damage && m_player_hit_timer <= 0.0){
|
||||||
|
LocalPlayer *player = env->getLocalPlayer();
|
||||||
|
assert(player);
|
||||||
|
|
||||||
|
v3f playerpos = player->getPosition();
|
||||||
|
v2f playerpos_2d(playerpos.X,playerpos.Z);
|
||||||
|
v2f objectpos_2d(m_position.X,m_position.Z);
|
||||||
|
|
||||||
|
if(fabs(m_position.Y - playerpos.Y) < m_player_hit_distance*BS &&
|
||||||
|
objectpos_2d.getDistanceFrom(playerpos_2d) < m_player_hit_distance*BS)
|
||||||
|
{
|
||||||
|
env->damageLocalPlayer(m_player_hit_damage);
|
||||||
|
m_player_hit_timer = m_player_hit_interval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Run timers */
|
||||||
|
|
||||||
|
m_player_hit_timer -= dtime;
|
||||||
|
|
||||||
|
if(m_damage_visual_timer >= 0){
|
||||||
|
m_damage_visual_timer -= dtime;
|
||||||
|
if(m_damage_visual_timer <= 0){
|
||||||
|
infostream<<"id="<<m_id<<" damage visual ended"<<std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_walking_unset_timer += dtime;
|
||||||
|
if(m_walking_unset_timer >= 1.0){
|
||||||
|
m_walking = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_shooting_unset_timer -= dtime;
|
||||||
|
if(m_shooting_unset_timer <= 0.0){
|
||||||
|
if(m_bright_shooting){
|
||||||
|
u8 li = decode_light(m_last_light);
|
||||||
|
video::SColor color(255,li,li,li);
|
||||||
|
bill->setColor(color);
|
||||||
|
m_bright_shooting = false;
|
||||||
|
}
|
||||||
|
m_shooting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void processMessage(const std::string &data)
|
||||||
|
{
|
||||||
|
//infostream<<"MobV2CAO: Got message"<<std::endl;
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// command
|
||||||
|
u8 cmd = readU8(is);
|
||||||
|
|
||||||
|
// Move
|
||||||
|
if(cmd == AO_Message_type::SetPosition)
|
||||||
|
{
|
||||||
|
// pos
|
||||||
|
m_position = readV3F1000(is);
|
||||||
|
pos_translator.update(m_position);
|
||||||
|
// yaw
|
||||||
|
m_yaw = readF1000(is);
|
||||||
|
|
||||||
|
m_walking = true;
|
||||||
|
m_walking_unset_timer = 0;
|
||||||
|
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
// Damage
|
||||||
|
else if(cmd == AO_Message_type::TakeDamage)
|
||||||
|
{
|
||||||
|
//u16 damage = readU16(is);
|
||||||
|
|
||||||
|
/*u8 li = decode_light(m_last_light);
|
||||||
|
if(li >= 100)
|
||||||
|
li = 30;
|
||||||
|
else
|
||||||
|
li = 255;*/
|
||||||
|
|
||||||
|
/*video::SColor color(255,255,0,0);
|
||||||
|
m_node->setColor(color);
|
||||||
|
|
||||||
|
m_damage_visual_timer = 0.2;*/
|
||||||
|
}
|
||||||
|
// Trigger shooting
|
||||||
|
else if(cmd == AO_Message_type::Shoot)
|
||||||
|
{
|
||||||
|
// length
|
||||||
|
m_shooting_unset_timer = readF1000(is);
|
||||||
|
// bright?
|
||||||
|
m_bright_shooting = readU8(is);
|
||||||
|
if(m_bright_shooting){
|
||||||
|
u8 li = 255;
|
||||||
|
video::SColor color(255,li,li,li);
|
||||||
|
m_node->setColor(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_shooting = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize(const std::string &data)
|
||||||
|
{
|
||||||
|
//infostream<<"MobV2CAO: Got init data"<<std::endl;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// version
|
||||||
|
u8 version = readU8(is);
|
||||||
|
// check version
|
||||||
|
if(version != 0){
|
||||||
|
infostream<<__FUNCTION_NAME<<": Invalid version"<<std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream tmp_os(std::ios::binary);
|
||||||
|
decompressZlib(is, tmp_os);
|
||||||
|
std::istringstream tmp_is(tmp_os.str(), std::ios::binary);
|
||||||
|
m_properties->parseConfigLines(tmp_is, "MobArgsEnd");
|
||||||
|
|
||||||
|
infostream<<"MobV2CAO::initialize(): got properties:"<<std::endl;
|
||||||
|
m_properties->writeLines(infostream);
|
||||||
|
|
||||||
|
m_properties->setDefault("looks", "dummy_default");
|
||||||
|
m_properties->setDefault("yaw", "0");
|
||||||
|
m_properties->setDefault("pos", "(0,0,0)");
|
||||||
|
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_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");
|
||||||
|
|
||||||
|
pos_translator.init(m_position);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
core::aabbox3d<f32>* getSelectionBox()
|
||||||
|
{return &m_selection_box;}
|
||||||
|
|
||||||
|
v3f getPosition()
|
||||||
|
{return pos_translator.vect_show;}
|
||||||
|
|
||||||
|
bool 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
IntervalLimiter m_attack_interval;
|
||||||
|
core::aabbox3d<f32> m_selection_box;
|
||||||
|
scene::IBillboardSceneNode *m_node;
|
||||||
|
v3f m_position;
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
MobV2CAO proto_MobV2CAO(NULL, NULL);
|
||||||
283
src/content_cao_oerkki1.cpp
Normal file
283
src/content_cao_oerkki1.cpp
Normal file
@@ -0,0 +1,283 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2012 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 "inventory.h"
|
||||||
|
#include "content_cao.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Oerkki1CAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Oerkki1CAO : public ClientActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Oerkki1CAO(IGameDef *gamedef, ClientEnvironment *env):
|
||||||
|
ClientActiveObject(0, gamedef, env),
|
||||||
|
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.,BS/3.),
|
||||||
|
m_node(NULL),
|
||||||
|
m_position(v3f(0,10*BS,0)),
|
||||||
|
m_yaw(0),
|
||||||
|
m_damage_visual_timer(0),
|
||||||
|
m_damage_texture_enabled(false)
|
||||||
|
{
|
||||||
|
ClientActiveObject::registerType(getType(), create);
|
||||||
|
}
|
||||||
|
|
||||||
|
~Oerkki1CAO()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u8 getType() const { return ACTIVEOBJECT_TYPE_OERKKI1; }
|
||||||
|
|
||||||
|
static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
|
||||||
|
{
|
||||||
|
return new Oerkki1CAO(gamedef, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||||
|
IrrlichtDevice *irr)
|
||||||
|
{
|
||||||
|
if(m_node != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//video::IVideoDriver* driver = smgr->getVideoDriver();
|
||||||
|
|
||||||
|
scene::SMesh *mesh = new scene::SMesh();
|
||||||
|
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||||
|
video::SColor c(255,255,255,255);
|
||||||
|
video::S3DVertex vertices[4] =
|
||||||
|
{
|
||||||
|
video::S3DVertex(-BS/2-BS,0,0, 0,0,0, c, 0,1),
|
||||||
|
video::S3DVertex(BS/2+BS,0,0, 0,0,0, c, 1,1),
|
||||||
|
video::S3DVertex(BS/2+BS,BS*2,0, 0,0,0, c, 1,0),
|
||||||
|
video::S3DVertex(-BS/2-BS,BS*2,0, 0,0,0, c, 0,0),
|
||||||
|
};
|
||||||
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
|
buf->append(vertices, 4, indices, 6);
|
||||||
|
// Set material
|
||||||
|
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||||
|
//buf->getMaterial().setTexture(0, NULL);
|
||||||
|
buf->getMaterial().setTexture(0, tsrc->getTextureRaw("oerkki1.png"));
|
||||||
|
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
|
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||||
|
// Add to mesh
|
||||||
|
mesh->addMeshBuffer(buf);
|
||||||
|
buf->drop();
|
||||||
|
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
||||||
|
mesh->drop();
|
||||||
|
// Set it to use the materials of the meshbuffers directly.
|
||||||
|
// This is needed for changing the texture in the future
|
||||||
|
m_node->setReadOnlyMaterials(true);
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeFromScene()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node->remove();
|
||||||
|
m_node = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateLight(u8 light_at_pos)
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(light_at_pos <= 2)
|
||||||
|
{
|
||||||
|
m_node->setVisible(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->setVisible(true);
|
||||||
|
|
||||||
|
u8 li = decode_light(light_at_pos);
|
||||||
|
video::SColor color(255,li,li,li);
|
||||||
|
setMeshColor(m_node->getMesh(), color);
|
||||||
|
}
|
||||||
|
|
||||||
|
v3s16 getLightPosition()
|
||||||
|
{
|
||||||
|
return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateNodePos()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//m_node->setPosition(m_position);
|
||||||
|
m_node->setPosition(pos_translator.vect_show);
|
||||||
|
|
||||||
|
v3f rot = m_node->getRotation();
|
||||||
|
rot.Y = 180.0 - m_yaw + 90.0;
|
||||||
|
m_node->setRotation(rot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void step(float dtime, ClientEnvironment *env)
|
||||||
|
{
|
||||||
|
ITextureSource *tsrc = m_gamedef->tsrc();
|
||||||
|
|
||||||
|
pos_translator.translate(dtime);
|
||||||
|
updateNodePos();
|
||||||
|
|
||||||
|
LocalPlayer *player = env->getLocalPlayer();
|
||||||
|
assert(player);
|
||||||
|
|
||||||
|
v3f playerpos = player->getPosition();
|
||||||
|
v2f playerpos_2d(playerpos.X,playerpos.Z);
|
||||||
|
v2f objectpos_2d(m_position.X,m_position.Z);
|
||||||
|
|
||||||
|
if(fabs(m_position.Y - playerpos.Y) < 1.5*BS &&
|
||||||
|
objectpos_2d.getDistanceFrom(playerpos_2d) < 1.5*BS)
|
||||||
|
{
|
||||||
|
if(m_attack_interval.step(dtime, 0.5))
|
||||||
|
{
|
||||||
|
env->damageLocalPlayer(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_damage_visual_timer > 0)
|
||||||
|
{
|
||||||
|
if(!m_damage_texture_enabled)
|
||||||
|
{
|
||||||
|
// Enable damage texture
|
||||||
|
if(m_node)
|
||||||
|
{
|
||||||
|
/*video::IVideoDriver* driver =
|
||||||
|
m_node->getSceneManager()->getVideoDriver();*/
|
||||||
|
|
||||||
|
scene::IMesh *mesh = m_node->getMesh();
|
||||||
|
if(mesh == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u16 mc = mesh->getMeshBufferCount();
|
||||||
|
for(u16 j=0; j<mc; j++)
|
||||||
|
{
|
||||||
|
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||||
|
buf->getMaterial().setTexture(0,
|
||||||
|
tsrc->getTextureRaw("oerkki1_damaged.png"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_damage_texture_enabled = true;
|
||||||
|
}
|
||||||
|
m_damage_visual_timer -= dtime;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(m_damage_texture_enabled)
|
||||||
|
{
|
||||||
|
// Disable damage texture
|
||||||
|
if(m_node)
|
||||||
|
{
|
||||||
|
/*video::IVideoDriver* driver =
|
||||||
|
m_node->getSceneManager()->getVideoDriver();*/
|
||||||
|
|
||||||
|
scene::IMesh *mesh = m_node->getMesh();
|
||||||
|
if(mesh == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u16 mc = mesh->getMeshBufferCount();
|
||||||
|
for(u16 j=0; j<mc; j++)
|
||||||
|
{
|
||||||
|
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||||
|
buf->getMaterial().setTexture(0,
|
||||||
|
tsrc->getTextureRaw("oerkki1.png"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_damage_texture_enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void processMessage(const std::string &data)
|
||||||
|
{
|
||||||
|
//infostream<<"Oerkki1CAO: Got message"<<std::endl;
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// command
|
||||||
|
u8 cmd = readU8(is);
|
||||||
|
if(cmd == AO_Message_type::SetPosition)
|
||||||
|
{
|
||||||
|
// pos
|
||||||
|
m_position = readV3F1000(is);
|
||||||
|
pos_translator.update(m_position);
|
||||||
|
// yaw
|
||||||
|
m_yaw = readF1000(is);
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
else if(cmd == AO_Message_type::TakeDamage)
|
||||||
|
{
|
||||||
|
//u16 damage = readU8(is);
|
||||||
|
m_damage_visual_timer = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize(const std::string &data)
|
||||||
|
{
|
||||||
|
//infostream<<"Oerkki1CAO: Got init data"<<std::endl;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// version
|
||||||
|
u8 version = readU8(is);
|
||||||
|
// check version
|
||||||
|
if(version != 0)
|
||||||
|
return;
|
||||||
|
// pos
|
||||||
|
m_position = readV3F1000(is);
|
||||||
|
pos_translator.init(m_position);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
core::aabbox3d<f32>* getSelectionBox()
|
||||||
|
{return &m_selection_box;}
|
||||||
|
|
||||||
|
v3f getPosition()
|
||||||
|
{return pos_translator.vect_show;}
|
||||||
|
|
||||||
|
bool directReportPunch(const std::string &toolname, v3f dir)
|
||||||
|
{
|
||||||
|
m_damage_visual_timer = 1.0;
|
||||||
|
|
||||||
|
m_position += dir * BS;
|
||||||
|
pos_translator.sharpen();
|
||||||
|
pos_translator.update(m_position);
|
||||||
|
updateNodePos();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
IntervalLimiter m_attack_interval;
|
||||||
|
core::aabbox3d<f32> m_selection_box;
|
||||||
|
scene::IMeshSceneNode *m_node;
|
||||||
|
v3f m_position;
|
||||||
|
float m_yaw;
|
||||||
|
SmoothTranslator pos_translator;
|
||||||
|
float m_damage_visual_timer;
|
||||||
|
bool m_damage_texture_enabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
Oerkki1CAO proto_Oerkki1CAO(NULL, NULL);
|
||||||
315
src/content_cao_player.cpp
Normal file
315
src/content_cao_player.cpp
Normal file
@@ -0,0 +1,315 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2012 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_cao.h"
|
||||||
|
#include "clientlinkableobject.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
PlayerCAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
class PlayerCAO : public ClientActiveObject, public ClientLinkableObject
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
core::aabbox3d<f32> m_selection_box;
|
||||||
|
scene::IMeshSceneNode *m_node;
|
||||||
|
scene::ITextSceneNode* m_text;
|
||||||
|
std::string m_name;
|
||||||
|
v3f m_position;
|
||||||
|
float m_yaw;
|
||||||
|
SmoothTranslator pos_translator;
|
||||||
|
bool m_is_local_player;
|
||||||
|
LocalPlayer *m_local_player;
|
||||||
|
float m_damage_visual_timer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PlayerCAO(IGameDef *gamedef, ClientEnvironment *env):
|
||||||
|
ClientActiveObject(0, gamedef, env),
|
||||||
|
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.0,BS/3.),
|
||||||
|
m_node(NULL),
|
||||||
|
m_text(NULL),
|
||||||
|
m_position(v3f(0,10*BS,0)),
|
||||||
|
m_yaw(0),
|
||||||
|
m_is_local_player(false),
|
||||||
|
m_local_player(NULL),
|
||||||
|
m_damage_visual_timer(0)
|
||||||
|
{
|
||||||
|
if(gamedef == NULL)
|
||||||
|
ClientActiveObject::registerType(getType(), create);
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize(const std::string &data)
|
||||||
|
{
|
||||||
|
infostream<<"PlayerCAO: Got init data"<<std::endl;
|
||||||
|
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// version
|
||||||
|
u8 version = readU8(is);
|
||||||
|
// check version
|
||||||
|
if(version != 0)
|
||||||
|
return;
|
||||||
|
// name
|
||||||
|
m_name = deSerializeString(is);
|
||||||
|
// pos
|
||||||
|
m_position = readV3F1000(is);
|
||||||
|
// yaw
|
||||||
|
m_yaw = readF1000(is);
|
||||||
|
|
||||||
|
pos_translator.init(m_position);
|
||||||
|
|
||||||
|
Player *player = m_env->getPlayer(m_name.c_str());
|
||||||
|
if(player && player->isLocal()){
|
||||||
|
m_is_local_player = true;
|
||||||
|
m_local_player = (LocalPlayer*)player;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~PlayerCAO()
|
||||||
|
{
|
||||||
|
if(m_node)
|
||||||
|
m_node->remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u8 getType() const { return ACTIVEOBJECT_TYPE_PLAYER; }
|
||||||
|
|
||||||
|
static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
|
||||||
|
{
|
||||||
|
return new PlayerCAO(gamedef, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
core::aabbox3d<f32>* getSelectionBox()
|
||||||
|
{
|
||||||
|
if(m_is_local_player)
|
||||||
|
return NULL;
|
||||||
|
return &m_selection_box;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||||
|
IrrlichtDevice *irr)
|
||||||
|
{
|
||||||
|
if(m_node != NULL)
|
||||||
|
return;
|
||||||
|
if(m_is_local_player)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//video::IVideoDriver* driver = smgr->getVideoDriver();
|
||||||
|
gui::IGUIEnvironment* gui = irr->getGUIEnvironment();
|
||||||
|
|
||||||
|
scene::SMesh *mesh = new scene::SMesh();
|
||||||
|
{ // Front
|
||||||
|
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||||
|
video::SColor c(255,255,255,255);
|
||||||
|
video::S3DVertex vertices[4] =
|
||||||
|
{
|
||||||
|
video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
|
||||||
|
video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
|
||||||
|
video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
|
||||||
|
video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
|
||||||
|
};
|
||||||
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
|
buf->append(vertices, 4, indices, 6);
|
||||||
|
// Set material
|
||||||
|
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
|
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||||
|
// Add to mesh
|
||||||
|
mesh->addMeshBuffer(buf);
|
||||||
|
buf->drop();
|
||||||
|
}
|
||||||
|
{ // Back
|
||||||
|
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||||
|
video::SColor c(255,255,255,255);
|
||||||
|
video::S3DVertex vertices[4] =
|
||||||
|
{
|
||||||
|
video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
|
||||||
|
video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
|
||||||
|
video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
|
||||||
|
video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
|
||||||
|
};
|
||||||
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
|
buf->append(vertices, 4, indices, 6);
|
||||||
|
// Set material
|
||||||
|
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
|
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||||
|
// Add to mesh
|
||||||
|
mesh->addMeshBuffer(buf);
|
||||||
|
buf->drop();
|
||||||
|
}
|
||||||
|
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
||||||
|
mesh->drop();
|
||||||
|
// Set it to use the materials of the meshbuffers directly.
|
||||||
|
// This is needed for changing the texture in the future
|
||||||
|
m_node->setReadOnlyMaterials(true);
|
||||||
|
updateNodePos();
|
||||||
|
|
||||||
|
// Add a text node for showing the name
|
||||||
|
std::wstring wname = narrow_to_wide(m_name);
|
||||||
|
m_text = smgr->addTextSceneNode(gui->getBuiltInFont(),
|
||||||
|
wname.c_str(), video::SColor(255,255,255,255), m_node);
|
||||||
|
m_text->setPosition(v3f(0, (f32)BS*2.1, 0));
|
||||||
|
|
||||||
|
updateTextures("");
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeFromScene()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node->remove();
|
||||||
|
m_node = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateLight(u8 light_at_pos)
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node->setVisible(true);
|
||||||
|
|
||||||
|
u8 li = decode_light(light_at_pos);
|
||||||
|
video::SColor color(255,li,li,li);
|
||||||
|
setMeshColor(m_node->getMesh(), color);
|
||||||
|
}
|
||||||
|
|
||||||
|
v3s16 getLightPosition()
|
||||||
|
{
|
||||||
|
return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateNodePos()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node->setPosition(pos_translator.vect_show);
|
||||||
|
|
||||||
|
v3f rot = m_node->getRotation();
|
||||||
|
rot.Y = -m_yaw;
|
||||||
|
m_node->setRotation(rot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void step(float dtime, ClientEnvironment *env)
|
||||||
|
{
|
||||||
|
if(!isLinked()) {
|
||||||
|
pos_translator.translate(dtime);
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_damage_visual_timer > 0){
|
||||||
|
m_damage_visual_timer -= dtime;
|
||||||
|
if(m_damage_visual_timer <= 0){
|
||||||
|
updateTextures("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void processMessage(const std::string &data)
|
||||||
|
{
|
||||||
|
//infostream<<"PlayerCAO: Got message"<<std::endl;
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// command
|
||||||
|
u8 cmd = readU8(is);
|
||||||
|
if(cmd == AO_Message_type::SetPosition) // update position
|
||||||
|
{
|
||||||
|
// pos
|
||||||
|
m_position = readV3F1000(is);
|
||||||
|
// yaw
|
||||||
|
m_yaw = readF1000(is);
|
||||||
|
|
||||||
|
pos_translator.update(m_position, false);
|
||||||
|
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
else if(cmd == AO_Message_type::Punched) // punched
|
||||||
|
{
|
||||||
|
// damage
|
||||||
|
s16 damage = readS16(is);
|
||||||
|
|
||||||
|
if(m_is_local_player)
|
||||||
|
m_env->damageLocalPlayer(damage, false);
|
||||||
|
|
||||||
|
m_damage_visual_timer = 0.5;
|
||||||
|
updateTextures("^[brighten");
|
||||||
|
}
|
||||||
|
else if (handleLinkUnlinkMessages(cmd,&is,this->m_env))
|
||||||
|
{
|
||||||
|
//Link unlink already done in handleLinkUnlinkMessages!
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateTextures(const std::string &mod)
|
||||||
|
{
|
||||||
|
if(!m_node)
|
||||||
|
return;
|
||||||
|
ITextureSource *tsrc = m_gamedef->tsrc();
|
||||||
|
scene::IMesh *mesh = m_node->getMesh();
|
||||||
|
if(mesh){
|
||||||
|
{
|
||||||
|
std::string tname = "player.png";
|
||||||
|
tname += mod;
|
||||||
|
scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
|
||||||
|
buf->getMaterial().setTexture(0,
|
||||||
|
tsrc->getTextureRaw(tname));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::string tname = "player_back.png";
|
||||||
|
tname += mod;
|
||||||
|
scene::IMeshBuffer *buf = mesh->getMeshBuffer(1);
|
||||||
|
buf->getMaterial().setTexture(0,
|
||||||
|
tsrc->getTextureRaw(tname));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void setPosition(v3f toset, float dtime){
|
||||||
|
if (isLinked()) {
|
||||||
|
this->m_position = toset + this->m_linkOffset;
|
||||||
|
pos_translator.update(this->m_position,false);
|
||||||
|
updateNodePos();
|
||||||
|
|
||||||
|
if(m_is_local_player) {
|
||||||
|
m_local_player->setPosition(this->m_position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
errorstream<<"Got linked position update but not linked"<< std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateLinkState(bool value) {
|
||||||
|
if(m_is_local_player) {
|
||||||
|
m_local_player->Link(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline v3f getPosition() { return m_position; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
PlayerCAO proto_PlayerCAO(NULL, NULL);
|
||||||
183
src/content_cao_rat.cpp
Normal file
183
src/content_cao_rat.cpp
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2012 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 "inventory.h"
|
||||||
|
#include "content_cao.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
RatCAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
class RatCAO : public ClientActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RatCAO(IGameDef *gamedef, ClientEnvironment *env):
|
||||||
|
ClientActiveObject(0, gamedef, env),
|
||||||
|
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
|
||||||
|
m_node(NULL),
|
||||||
|
m_position(v3f(0,10*BS,0)),
|
||||||
|
m_yaw(0)
|
||||||
|
{
|
||||||
|
ClientActiveObject::registerType(getType(), create);
|
||||||
|
}
|
||||||
|
|
||||||
|
~RatCAO()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u8 getType() const { return ACTIVEOBJECT_TYPE_RAT; }
|
||||||
|
|
||||||
|
static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
|
||||||
|
{
|
||||||
|
return new RatCAO(gamedef, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||||
|
IrrlichtDevice *irr)
|
||||||
|
{
|
||||||
|
if(m_node != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//video::IVideoDriver* driver = smgr->getVideoDriver();
|
||||||
|
|
||||||
|
scene::SMesh *mesh = new scene::SMesh();
|
||||||
|
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||||
|
video::SColor c(255,255,255,255);
|
||||||
|
video::S3DVertex vertices[4] =
|
||||||
|
{
|
||||||
|
video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
|
||||||
|
video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
|
||||||
|
video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
|
||||||
|
video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
|
||||||
|
};
|
||||||
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
|
buf->append(vertices, 4, indices, 6);
|
||||||
|
// Set material
|
||||||
|
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||||
|
//buf->getMaterial().setTexture(0, NULL);
|
||||||
|
buf->getMaterial().setTexture(0, tsrc->getTextureRaw("rat.png"));
|
||||||
|
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
|
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||||
|
// Add to mesh
|
||||||
|
mesh->addMeshBuffer(buf);
|
||||||
|
buf->drop();
|
||||||
|
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
||||||
|
mesh->drop();
|
||||||
|
// Set it to use the materials of the meshbuffers directly.
|
||||||
|
// This is needed for changing the texture in the future
|
||||||
|
m_node->setReadOnlyMaterials(true);
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeFromScene()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node->remove();
|
||||||
|
m_node = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateLight(u8 light_at_pos)
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u8 li = decode_light(light_at_pos);
|
||||||
|
video::SColor color(255,li,li,li);
|
||||||
|
setMeshColor(m_node->getMesh(), color);
|
||||||
|
}
|
||||||
|
|
||||||
|
v3s16 getLightPosition()
|
||||||
|
{
|
||||||
|
return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateNodePos()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//m_node->setPosition(m_position);
|
||||||
|
m_node->setPosition(pos_translator.vect_show);
|
||||||
|
|
||||||
|
v3f rot = m_node->getRotation();
|
||||||
|
rot.Y = 180.0 - m_yaw;
|
||||||
|
m_node->setRotation(rot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void step(float dtime, ClientEnvironment *env)
|
||||||
|
{
|
||||||
|
pos_translator.translate(dtime);
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void processMessage(const std::string &data)
|
||||||
|
{
|
||||||
|
//infostream<<"RatCAO: Got message"<<std::endl;
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// command
|
||||||
|
u8 cmd = readU8(is);
|
||||||
|
if(cmd == AO_Message_type::SetPosition)
|
||||||
|
{
|
||||||
|
// pos
|
||||||
|
m_position = readV3F1000(is);
|
||||||
|
pos_translator.update(m_position);
|
||||||
|
// yaw
|
||||||
|
m_yaw = readF1000(is);
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize(const std::string &data)
|
||||||
|
{
|
||||||
|
//infostream<<"RatCAO: Got init data"<<std::endl;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// version
|
||||||
|
u8 version = readU8(is);
|
||||||
|
// check version
|
||||||
|
if(version != 0)
|
||||||
|
return;
|
||||||
|
// pos
|
||||||
|
m_position = readV3F1000(is);
|
||||||
|
pos_translator.init(m_position);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
core::aabbox3d<f32>* getSelectionBox()
|
||||||
|
{return &m_selection_box;}
|
||||||
|
|
||||||
|
v3f getPosition()
|
||||||
|
{return pos_translator.vect_show;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
core::aabbox3d<f32> m_selection_box;
|
||||||
|
scene::IMeshSceneNode *m_node;
|
||||||
|
v3f m_position;
|
||||||
|
float m_yaw;
|
||||||
|
SmoothTranslator pos_translator;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
RatCAO proto_RatCAO(NULL, NULL);
|
||||||
144
src/content_cao_test.cpp
Normal file
144
src/content_cao_test.cpp
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2012 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_cao.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
TestCAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
class TestCAO : public ClientActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
TestCAO(IGameDef *gamedef, ClientEnvironment *env):
|
||||||
|
ClientActiveObject(0, gamedef, env),
|
||||||
|
m_node(NULL),
|
||||||
|
m_position(v3f(0,10*BS,0))
|
||||||
|
{
|
||||||
|
ClientActiveObject::registerType(getType(), create);
|
||||||
|
}
|
||||||
|
|
||||||
|
~TestCAO()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
|
||||||
|
{
|
||||||
|
return new TestCAO(gamedef, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u8 getType() const
|
||||||
|
{ return ACTIVEOBJECT_TYPE_TEST; }
|
||||||
|
|
||||||
|
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||||
|
IrrlichtDevice *irr)
|
||||||
|
{
|
||||||
|
if(m_node != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//video::IVideoDriver* driver = smgr->getVideoDriver();
|
||||||
|
|
||||||
|
scene::SMesh *mesh = new scene::SMesh();
|
||||||
|
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||||
|
video::SColor c(255,255,255,255);
|
||||||
|
video::S3DVertex vertices[4] =
|
||||||
|
{
|
||||||
|
video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
|
||||||
|
video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
|
||||||
|
video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
|
||||||
|
video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),
|
||||||
|
};
|
||||||
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
|
buf->append(vertices, 4, indices, 6);
|
||||||
|
// Set material
|
||||||
|
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||||
|
buf->getMaterial().setTexture(0, tsrc->getTextureRaw("rat.png"));
|
||||||
|
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
|
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||||
|
// Add to mesh
|
||||||
|
mesh->addMeshBuffer(buf);
|
||||||
|
buf->drop();
|
||||||
|
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
||||||
|
mesh->drop();
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeFromScene()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node->remove();
|
||||||
|
m_node = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateLight(u8 light_at_pos)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
v3s16 getLightPosition()
|
||||||
|
{
|
||||||
|
return floatToInt(m_position, BS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateNodePos()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node->setPosition(m_position);
|
||||||
|
//m_node->setRotation(v3f(0, 45, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void step(float dtime, ClientEnvironment *env)
|
||||||
|
{
|
||||||
|
if(m_node)
|
||||||
|
{
|
||||||
|
v3f rot = m_node->getRotation();
|
||||||
|
//infostream<<"dtime="<<dtime<<", rot.Y="<<rot.Y<<std::endl;
|
||||||
|
rot.Y += dtime * 180;
|
||||||
|
m_node->setRotation(rot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void processMessage(const std::string &data)
|
||||||
|
{
|
||||||
|
infostream<<"TestCAO: Got data: "<<data<<std::endl;
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
u16 cmd;
|
||||||
|
is>>cmd;
|
||||||
|
if(cmd == AO_Message_type::SetPosition)
|
||||||
|
{
|
||||||
|
v3f newpos;
|
||||||
|
is>>newpos.X;
|
||||||
|
is>>newpos.Y;
|
||||||
|
is>>newpos.Z;
|
||||||
|
m_position = newpos;
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
scene::IMeshSceneNode *m_node;
|
||||||
|
v3f m_position;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
TestCAO proto_TestCAO(NULL, NULL);
|
||||||
@@ -20,17 +20,27 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#ifndef CONTENT_OBJECT_HEADER
|
#ifndef CONTENT_OBJECT_HEADER
|
||||||
#define CONTENT_OBJECT_HEADER
|
#define CONTENT_OBJECT_HEADER
|
||||||
|
|
||||||
#define ACTIVEOBJECT_TYPE_TEST 1
|
#define ACTIVEOBJECT_TYPE_TEST 0x01
|
||||||
#define ACTIVEOBJECT_TYPE_ITEM 2
|
#define ACTIVEOBJECT_TYPE_ITEM 0x02
|
||||||
#define ACTIVEOBJECT_TYPE_RAT 3
|
#define ACTIVEOBJECT_TYPE_RAT 0x03
|
||||||
#define ACTIVEOBJECT_TYPE_OERKKI1 4
|
#define ACTIVEOBJECT_TYPE_OERKKI1 0x04
|
||||||
#define ACTIVEOBJECT_TYPE_FIREFLY 5
|
#define ACTIVEOBJECT_TYPE_FIREFLY 0x05
|
||||||
#define ACTIVEOBJECT_TYPE_MOBV2 6
|
#define ACTIVEOBJECT_TYPE_MOBV2 0x06
|
||||||
|
#define ACTIVEOBJECT_TYPE_LUAENTITY 0x07
|
||||||
#define ACTIVEOBJECT_TYPE_LUAENTITY 7
|
|
||||||
|
|
||||||
// Special type, not stored as a static object
|
// Special type, not stored as a static object
|
||||||
#define ACTIVEOBJECT_TYPE_PLAYER 100
|
#define ACTIVEOBJECT_TYPE_PLAYER 0x64
|
||||||
|
|
||||||
|
struct AO_Message_type {
|
||||||
|
static const u8 SetPosition = 0x00;
|
||||||
|
static const u8 SetTextureMod = 0x01;
|
||||||
|
static const u8 SetSprite = 0x02;
|
||||||
|
static const u8 Punched = 0x03;
|
||||||
|
static const u8 TakeDamage = 0x04;
|
||||||
|
static const u8 Shoot = 0x05;
|
||||||
|
static const u8 Link = 0x06;
|
||||||
|
static const u8 UnLink = 0x07;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
1675
src/content_sao.cpp
1675
src/content_sao.cpp
File diff suppressed because it is too large
Load Diff
@@ -22,223 +22,25 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
#include "serverobject.h"
|
#include "serverobject.h"
|
||||||
#include "content_object.h"
|
#include "content_object.h"
|
||||||
|
#include "collision.h"
|
||||||
class TestSAO : public ServerActiveObject
|
#include "environment.h"
|
||||||
{
|
#include "settings.h"
|
||||||
public:
|
#include "main.h" // For g_profiler
|
||||||
TestSAO(ServerEnvironment *env, v3f pos);
|
#include "profiler.h"
|
||||||
u8 getType() const
|
#include "serialization.h" // For compressZlib
|
||||||
{return ACTIVEOBJECT_TYPE_TEST;}
|
#include "materials.h" // For MaterialProperties
|
||||||
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
|
#include "tooldef.h" // ToolDiggingProperties
|
||||||
const std::string &data);
|
|
||||||
void step(float dtime, bool send_recommended);
|
|
||||||
private:
|
|
||||||
float m_timer1;
|
|
||||||
float m_age;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ItemSAO : public ServerActiveObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ItemSAO(ServerEnvironment *env, v3f pos,
|
|
||||||
const std::string inventorystring);
|
|
||||||
u8 getType() const
|
|
||||||
{return ACTIVEOBJECT_TYPE_ITEM;}
|
|
||||||
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
|
|
||||||
const std::string &data);
|
|
||||||
void step(float dtime, bool send_recommended);
|
|
||||||
std::string getClientInitializationData();
|
|
||||||
std::string getStaticData();
|
|
||||||
InventoryItem* createInventoryItem();
|
|
||||||
void punch(ServerActiveObject *puncher, float time_from_last_punch);
|
|
||||||
float getMinimumSavedMovement(){ return 0.1*BS; }
|
|
||||||
private:
|
|
||||||
std::string m_inventorystring;
|
|
||||||
v3f m_speed_f;
|
|
||||||
v3f m_last_sent_position;
|
|
||||||
IntervalLimiter m_move_interval;
|
|
||||||
};
|
|
||||||
|
|
||||||
class RatSAO : public ServerActiveObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
RatSAO(ServerEnvironment *env, v3f pos);
|
|
||||||
u8 getType() const
|
|
||||||
{return ACTIVEOBJECT_TYPE_RAT;}
|
|
||||||
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
|
|
||||||
const std::string &data);
|
|
||||||
void step(float dtime, bool send_recommended);
|
|
||||||
std::string getClientInitializationData();
|
|
||||||
std::string getStaticData();
|
|
||||||
void punch(ServerActiveObject *puncher, float time_from_last_punch);
|
|
||||||
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, v3f pos);
|
|
||||||
u8 getType() const
|
|
||||||
{return ACTIVEOBJECT_TYPE_OERKKI1;}
|
|
||||||
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
|
|
||||||
const std::string &data);
|
|
||||||
void step(float dtime, bool send_recommended);
|
|
||||||
std::string getClientInitializationData();
|
|
||||||
std::string getStaticData();
|
|
||||||
void punch(ServerActiveObject *puncher, float time_from_last_punch);
|
|
||||||
bool isPeaceful(){return false;}
|
|
||||||
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, v3f pos);
|
|
||||||
u8 getType() const
|
|
||||||
{return ACTIVEOBJECT_TYPE_FIREFLY;}
|
|
||||||
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
|
|
||||||
const std::string &data);
|
|
||||||
void step(float dtime, bool send_recommended);
|
|
||||||
std::string getClientInitializationData();
|
|
||||||
std::string getStaticData();
|
|
||||||
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 Settings;
|
||||||
|
|
||||||
class MobV2SAO : public ServerActiveObject
|
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||||
{
|
|
||||||
public:
|
|
||||||
MobV2SAO(ServerEnvironment *env, v3f pos,
|
|
||||||
Settings *init_properties);
|
|
||||||
virtual ~MobV2SAO();
|
|
||||||
u8 getType() const
|
|
||||||
{return ACTIVEOBJECT_TYPE_MOBV2;}
|
|
||||||
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
|
|
||||||
const std::string &data);
|
|
||||||
std::string getStaticData();
|
|
||||||
std::string getClientInitializationData();
|
|
||||||
void step(float dtime, bool send_recommended);
|
|
||||||
void punch(ServerActiveObject *puncher, float time_from_last_punch);
|
|
||||||
bool isPeaceful();
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LuaEntityProperties;
|
void accelerate_xz(v3f &speed, v3f target_speed, f32 max_increase);
|
||||||
|
bool checkFreePosition(Map *map, v3s16 p0, v3s16 size);
|
||||||
class LuaEntitySAO : public ServerActiveObject
|
bool checkWalkablePosition(Map *map, v3s16 p0);
|
||||||
{
|
bool checkFreeAndWalkablePosition(Map *map, v3s16 p0, v3s16 size);
|
||||||
public:
|
void get_random_u32_array(u32 a[], u32 len);
|
||||||
LuaEntitySAO(ServerEnvironment *env, v3f pos,
|
void explodeSquare(Map *map, v3s16 p0, v3s16 size);
|
||||||
const std::string &name, const std::string &state);
|
|
||||||
~LuaEntitySAO();
|
|
||||||
u8 getType() const
|
|
||||||
{return ACTIVEOBJECT_TYPE_LUAENTITY;}
|
|
||||||
virtual void addedToEnvironment();
|
|
||||||
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
|
|
||||||
const std::string &data);
|
|
||||||
void step(float dtime, bool send_recommended);
|
|
||||||
std::string getClientInitializationData();
|
|
||||||
std::string getStaticData();
|
|
||||||
void punch(ServerActiveObject *puncher, float time_from_last_punch);
|
|
||||||
void rightClick(ServerActiveObject *clicker);
|
|
||||||
void setPos(v3f pos);
|
|
||||||
void moveTo(v3f pos, bool continuous);
|
|
||||||
float getMinimumSavedMovement();
|
|
||||||
/* LuaEntitySAO-specific */
|
|
||||||
void setVelocity(v3f velocity);
|
|
||||||
v3f getVelocity();
|
|
||||||
void setAcceleration(v3f acceleration);
|
|
||||||
v3f getAcceleration();
|
|
||||||
void setYaw(float yaw);
|
|
||||||
float getYaw();
|
|
||||||
void setTextureMod(const std::string &mod);
|
|
||||||
void setSprite(v2s16 p, int num_frames, float framelength,
|
|
||||||
bool select_horiz_by_yawpitch);
|
|
||||||
std::string getName();
|
|
||||||
private:
|
|
||||||
void sendPosition(bool do_interpolate, bool is_movement_end);
|
|
||||||
|
|
||||||
std::string m_init_name;
|
|
||||||
std::string m_init_state;
|
|
||||||
bool m_registered;
|
|
||||||
struct LuaEntityProperties *m_prop;
|
|
||||||
|
|
||||||
v3f m_velocity;
|
|
||||||
v3f m_acceleration;
|
|
||||||
float m_yaw;
|
|
||||||
float m_last_sent_yaw;
|
|
||||||
v3f m_last_sent_position;
|
|
||||||
v3f m_last_sent_velocity;
|
|
||||||
float m_last_sent_position_timer;
|
|
||||||
float m_last_sent_move_precision;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
193
src/content_sao_firefly.cpp
Normal file
193
src/content_sao_firefly.cpp
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2012 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_sao_firefly.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
FireflySAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
FireflySAO::FireflySAO(ServerEnvironment *env, v3f pos):
|
||||||
|
ServerActiveObject(env, pos),
|
||||||
|
m_is_active(false),
|
||||||
|
m_speed_f(0,0,0)
|
||||||
|
{
|
||||||
|
ServerActiveObject::registerType(getType(), create);
|
||||||
|
|
||||||
|
m_oldpos = v3f(0,0,0);
|
||||||
|
m_last_sent_position = v3f(0,0,0);
|
||||||
|
m_yaw = 0;
|
||||||
|
m_counter1 = 0;
|
||||||
|
m_counter2 = 0;
|
||||||
|
m_age = 0;
|
||||||
|
m_touching_ground = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerActiveObject* FireflySAO::create(ServerEnvironment *env, v3f pos,
|
||||||
|
const std::string &data)
|
||||||
|
{
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
char buf[1];
|
||||||
|
// read version
|
||||||
|
is.read(buf, 1);
|
||||||
|
u8 version = buf[0];
|
||||||
|
// check if version is supported
|
||||||
|
if(version != 0)
|
||||||
|
return NULL;
|
||||||
|
return new FireflySAO(env, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FireflySAO::step(float dtime, bool send_recommended)
|
||||||
|
{
|
||||||
|
ScopeProfiler sp2(g_profiler, "FireflySAO::step avg", SPT_AVG);
|
||||||
|
|
||||||
|
assert(m_env);
|
||||||
|
|
||||||
|
if(m_is_active == false)
|
||||||
|
{
|
||||||
|
if(m_inactive_interval.step(dtime, 0.5)==false)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
The AI
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Apply (less) gravity
|
||||||
|
m_speed_f.Y -= dtime*3*BS;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Move around if some player is close
|
||||||
|
*/
|
||||||
|
bool player_is_close = false;
|
||||||
|
// Check connected players
|
||||||
|
core::list<Player*> players = m_env->getPlayers(true);
|
||||||
|
core::list<Player*>::Iterator i;
|
||||||
|
for(i = players.begin();
|
||||||
|
i != players.end(); i++)
|
||||||
|
{
|
||||||
|
Player *player = *i;
|
||||||
|
v3f playerpos = player->getPosition();
|
||||||
|
if(m_base_position.getDistanceFrom(playerpos) < BS*10.0)
|
||||||
|
{
|
||||||
|
player_is_close = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_is_active = player_is_close;
|
||||||
|
|
||||||
|
if(player_is_close == false)
|
||||||
|
{
|
||||||
|
m_speed_f.X = 0;
|
||||||
|
m_speed_f.Z = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Move around
|
||||||
|
v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
|
||||||
|
f32 speed = BS/2;
|
||||||
|
m_speed_f.X = speed * dir.X;
|
||||||
|
m_speed_f.Z = speed * dir.Z;
|
||||||
|
|
||||||
|
if(m_touching_ground && (m_oldpos - m_base_position).getLength()
|
||||||
|
< dtime*speed/2)
|
||||||
|
{
|
||||||
|
m_counter1 -= dtime;
|
||||||
|
if(m_counter1 < 0.0)
|
||||||
|
{
|
||||||
|
m_counter1 += 1.0;
|
||||||
|
m_speed_f.Y = 5.0*BS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
m_counter2 -= dtime;
|
||||||
|
if(m_counter2 < 0.0)
|
||||||
|
{
|
||||||
|
m_counter2 += (float)(myrand()%100)/100*3.0;
|
||||||
|
m_yaw += ((float)(myrand()%200)-100)/100*180;
|
||||||
|
m_yaw = wrapDegrees(m_yaw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_oldpos = m_base_position;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Move it, with collision detection
|
||||||
|
*/
|
||||||
|
|
||||||
|
core::aabbox3d<f32> box(-BS/3.,-BS*2/3.0,-BS/3., BS/3.,BS*4./3.,BS/3.);
|
||||||
|
collisionMoveResult moveresult;
|
||||||
|
// Maximum movement without glitches
|
||||||
|
f32 pos_max_d = BS*0.25;
|
||||||
|
// Limit speed
|
||||||
|
if(m_speed_f.getLength()*dtime > pos_max_d)
|
||||||
|
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
|
||||||
|
v3f pos_f = getBasePosition();
|
||||||
|
v3f pos_f_old = pos_f;
|
||||||
|
IGameDef *gamedef = m_env->getGameDef();
|
||||||
|
moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
|
||||||
|
pos_max_d, box, dtime, pos_f, m_speed_f);
|
||||||
|
m_touching_ground = moveresult.touching_ground;
|
||||||
|
|
||||||
|
setBasePosition(pos_f);
|
||||||
|
|
||||||
|
if(send_recommended == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
|
||||||
|
{
|
||||||
|
m_last_sent_position = pos_f;
|
||||||
|
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// command (0 = update position)
|
||||||
|
writeU8(os, AO_Message_type::SetPosition);
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string FireflySAO::getClientInitializationData()
|
||||||
|
{
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// version
|
||||||
|
writeU8(os, 0);
|
||||||
|
// pos
|
||||||
|
writeV3F1000(os, m_base_position);
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string FireflySAO::getStaticData()
|
||||||
|
{
|
||||||
|
//infostream<<__FUNCTION_NAME<<std::endl;
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// version
|
||||||
|
writeU8(os, 0);
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
FireflySAO proto_FireflySAO(NULL, v3f(0,0,0));
|
||||||
49
src/content_sao_firefly.h
Normal file
49
src/content_sao_firefly.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2012 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_SOA_FIREFLY_H_
|
||||||
|
#define CONTENT_SOA_FIREFLY_H_
|
||||||
|
|
||||||
|
#include "content_sao.h"
|
||||||
|
|
||||||
|
class FireflySAO : public ServerActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FireflySAO(ServerEnvironment *env, v3f pos);
|
||||||
|
u8 getType() const
|
||||||
|
{return ACTIVEOBJECT_TYPE_FIREFLY;}
|
||||||
|
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
|
||||||
|
const std::string &data);
|
||||||
|
void step(float dtime, bool send_recommended);
|
||||||
|
std::string getClientInitializationData();
|
||||||
|
std::string getStaticData();
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* CONTENT_SOA_FIREFLY_H_ */
|
||||||
167
src/content_sao_item.cpp
Normal file
167
src/content_sao_item.cpp
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2012 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_sao_item.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
ItemSAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
ItemSAO::ItemSAO(ServerEnvironment *env, v3f pos,
|
||||||
|
const std::string inventorystring):
|
||||||
|
ServerActiveObject(env, pos),
|
||||||
|
m_inventorystring(inventorystring),
|
||||||
|
m_speed_f(0,0,0),
|
||||||
|
m_last_sent_position(0,0,0)
|
||||||
|
{
|
||||||
|
ServerActiveObject::registerType(getType(), create);
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerActiveObject* ItemSAO::create(ServerEnvironment *env, v3f pos,
|
||||||
|
const std::string &data)
|
||||||
|
{
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
char buf[1];
|
||||||
|
// read version
|
||||||
|
is.read(buf, 1);
|
||||||
|
u8 version = buf[0];
|
||||||
|
// check if version is supported
|
||||||
|
if(version != 0)
|
||||||
|
return NULL;
|
||||||
|
std::string inventorystring = deSerializeString(is);
|
||||||
|
infostream<<"ItemSAO::create(): Creating item \""
|
||||||
|
<<inventorystring<<"\""<<std::endl;
|
||||||
|
return new ItemSAO(env, pos, inventorystring);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemSAO::step(float dtime, bool send_recommended)
|
||||||
|
{
|
||||||
|
ScopeProfiler sp2(g_profiler, "ItemSAO::step avg", SPT_AVG);
|
||||||
|
|
||||||
|
assert(m_env);
|
||||||
|
|
||||||
|
const float interval = 0.2;
|
||||||
|
if(m_move_interval.step(dtime, interval)==false)
|
||||||
|
return;
|
||||||
|
dtime = interval;
|
||||||
|
|
||||||
|
core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.);
|
||||||
|
collisionMoveResult moveresult;
|
||||||
|
// Apply gravity
|
||||||
|
m_speed_f += v3f(0, -dtime*9.81*BS, 0);
|
||||||
|
// Maximum movement without glitches
|
||||||
|
f32 pos_max_d = BS*0.25;
|
||||||
|
// Limit speed
|
||||||
|
if(m_speed_f.getLength()*dtime > pos_max_d)
|
||||||
|
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
|
||||||
|
v3f pos_f = getBasePosition();
|
||||||
|
v3f pos_f_old = pos_f;
|
||||||
|
IGameDef *gamedef = m_env->getGameDef();
|
||||||
|
moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
|
||||||
|
pos_max_d, box, dtime, pos_f, m_speed_f);
|
||||||
|
|
||||||
|
if(send_recommended == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
|
||||||
|
{
|
||||||
|
setBasePosition(pos_f);
|
||||||
|
m_last_sent_position = pos_f;
|
||||||
|
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
char buf[6];
|
||||||
|
// command (0 = update position)
|
||||||
|
buf[0] = AO_Message_type::SetPosition;
|
||||||
|
os.write(buf, 1);
|
||||||
|
// pos
|
||||||
|
writeS32((u8*)buf, m_base_position.X*1000);
|
||||||
|
os.write(buf, 4);
|
||||||
|
writeS32((u8*)buf, m_base_position.Y*1000);
|
||||||
|
os.write(buf, 4);
|
||||||
|
writeS32((u8*)buf, m_base_position.Z*1000);
|
||||||
|
os.write(buf, 4);
|
||||||
|
// create message and add to list
|
||||||
|
ActiveObjectMessage aom(getId(), false, os.str());
|
||||||
|
m_messages_out.push_back(aom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ItemSAO::getClientInitializationData()
|
||||||
|
{
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
char buf[6];
|
||||||
|
// version
|
||||||
|
buf[0] = 0;
|
||||||
|
os.write(buf, 1);
|
||||||
|
// pos
|
||||||
|
writeS32((u8*)buf, m_base_position.X*1000);
|
||||||
|
os.write(buf, 4);
|
||||||
|
writeS32((u8*)buf, m_base_position.Y*1000);
|
||||||
|
os.write(buf, 4);
|
||||||
|
writeS32((u8*)buf, m_base_position.Z*1000);
|
||||||
|
os.write(buf, 4);
|
||||||
|
// inventorystring
|
||||||
|
os<<serializeString(m_inventorystring);
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ItemSAO::getStaticData()
|
||||||
|
{
|
||||||
|
infostream<<__FUNCTION_NAME<<std::endl;
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
char buf[1];
|
||||||
|
// version
|
||||||
|
buf[0] = 0;
|
||||||
|
os.write(buf, 1);
|
||||||
|
// inventorystring
|
||||||
|
os<<serializeString(m_inventorystring);
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
InventoryItem * ItemSAO::createInventoryItem()
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
std::istringstream is(m_inventorystring, std::ios_base::binary);
|
||||||
|
IGameDef *gamedef = m_env->getGameDef();
|
||||||
|
InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
|
||||||
|
infostream<<__FUNCTION_NAME<<": m_inventorystring=\""
|
||||||
|
<<m_inventorystring<<"\" -> item="<<item
|
||||||
|
<<std::endl;
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
catch(SerializationError &e)
|
||||||
|
{
|
||||||
|
infostream<<__FUNCTION_NAME<<": serialization error: "
|
||||||
|
<<"m_inventorystring=\""<<m_inventorystring<<"\""<<std::endl;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemSAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
|
||||||
|
{
|
||||||
|
InventoryItem *item = createInventoryItem();
|
||||||
|
bool fits = puncher->addToInventory(item);
|
||||||
|
if(fits)
|
||||||
|
m_removed = true;
|
||||||
|
else
|
||||||
|
delete item;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
ItemSAO proto_ItemSAO(NULL, v3f(0,0,0), "");
|
||||||
47
src/content_sao_item.h
Normal file
47
src/content_sao_item.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2012 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_SAO_ITEM_H_
|
||||||
|
#define CONTENT_SAO_ITEM_H_
|
||||||
|
|
||||||
|
#include "content_sao.h"
|
||||||
|
|
||||||
|
class ItemSAO : public ServerActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ItemSAO(ServerEnvironment *env, v3f pos,
|
||||||
|
const std::string inventorystring);
|
||||||
|
u8 getType() const
|
||||||
|
{return ACTIVEOBJECT_TYPE_ITEM;}
|
||||||
|
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
|
||||||
|
const std::string &data);
|
||||||
|
void step(float dtime, bool send_recommended);
|
||||||
|
std::string getClientInitializationData();
|
||||||
|
std::string getStaticData();
|
||||||
|
InventoryItem* createInventoryItem();
|
||||||
|
void punch(ServerActiveObject *puncher, float time_from_last_punch);
|
||||||
|
float getMinimumSavedMovement(){ return 0.1*BS; }
|
||||||
|
private:
|
||||||
|
std::string m_inventorystring;
|
||||||
|
v3f m_speed_f;
|
||||||
|
v3f m_last_sent_position;
|
||||||
|
IntervalLimiter m_move_interval;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* CONTENT_SAO_ITEM_H_ */
|
||||||
344
src/content_sao_lua.cpp
Normal file
344
src/content_sao_lua.cpp
Normal file
@@ -0,0 +1,344 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2012 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 <iostream>
|
||||||
|
#include "content_sao_lua.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
LuaEntitySAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos,
|
||||||
|
const std::string &name, const std::string &state):
|
||||||
|
ServerActiveObject(env, pos),
|
||||||
|
m_init_name(name),
|
||||||
|
m_init_state(state),
|
||||||
|
m_registered(false),
|
||||||
|
m_prop(new LuaEntityProperties),
|
||||||
|
m_velocity(0,0,0),
|
||||||
|
m_acceleration(0,0,0),
|
||||||
|
m_yaw(0),
|
||||||
|
m_last_sent_yaw(0),
|
||||||
|
m_last_sent_position(0,0,0),
|
||||||
|
m_last_sent_velocity(0,0,0),
|
||||||
|
m_last_sent_position_timer(0),
|
||||||
|
m_last_sent_move_precision(0)
|
||||||
|
{
|
||||||
|
// Only register type if no environment supplied
|
||||||
|
if(env == NULL){
|
||||||
|
ServerActiveObject::registerType(getType(), create);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LuaEntitySAO::~LuaEntitySAO()
|
||||||
|
{
|
||||||
|
if(m_registered){
|
||||||
|
lua_State *L = m_env->getLua();
|
||||||
|
scriptapi_luaentity_rm(L, m_id);
|
||||||
|
}
|
||||||
|
delete m_prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaEntitySAO::addedToEnvironment()
|
||||||
|
{
|
||||||
|
ServerActiveObject::addedToEnvironment();
|
||||||
|
|
||||||
|
// Create entity from name and state
|
||||||
|
lua_State *L = m_env->getLua();
|
||||||
|
m_registered = scriptapi_luaentity_add(L, m_id, m_init_name.c_str(),
|
||||||
|
m_init_state.c_str());
|
||||||
|
|
||||||
|
if(m_registered){
|
||||||
|
// Get properties
|
||||||
|
scriptapi_luaentity_get_properties(L, m_id, m_prop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerActiveObject* LuaEntitySAO::create(ServerEnvironment *env, v3f pos,
|
||||||
|
const std::string &data)
|
||||||
|
{
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// read version
|
||||||
|
u8 version = readU8(is);
|
||||||
|
// check if version is supported
|
||||||
|
if(version != 0)
|
||||||
|
return NULL;
|
||||||
|
// read name
|
||||||
|
std::string name = deSerializeString(is);
|
||||||
|
// read state
|
||||||
|
std::string state = deSerializeLongString(is);
|
||||||
|
// create object
|
||||||
|
infostream<<"LuaEntitySAO::create(name=\""<<name<<"\" state=\""
|
||||||
|
<<state<<"\")"<<std::endl;
|
||||||
|
return new LuaEntitySAO(env, pos, name, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaEntitySAO::step(float dtime, bool send_recommended)
|
||||||
|
{
|
||||||
|
//errorstream << this << " step: old_vel=(" << m_velocity.X << "," << m_velocity.Y << "," << m_velocity.Z << ")" << std::endl;
|
||||||
|
//errorstream << this << " step: old_pos=(" << m_base_position.X << "," << m_base_position.Y << "," << m_base_position.Z << ")" << std::endl;
|
||||||
|
m_last_sent_position_timer += dtime;
|
||||||
|
|
||||||
|
if(m_prop->physical){
|
||||||
|
core::aabbox3d<f32> box = m_prop->collisionbox;
|
||||||
|
box.MinEdge *= BS;
|
||||||
|
box.MaxEdge *= BS;
|
||||||
|
collisionMoveResult moveresult;
|
||||||
|
f32 pos_max_d = BS*0.25; // Distance per iteration
|
||||||
|
v3f p_pos = getBasePosition();
|
||||||
|
v3f p_velocity = m_velocity;
|
||||||
|
IGameDef *gamedef = m_env->getGameDef();
|
||||||
|
moveresult = collisionMovePrecise(&m_env->getMap(), gamedef,
|
||||||
|
pos_max_d, box, dtime, p_pos, p_velocity);
|
||||||
|
// Apply results
|
||||||
|
setBasePosition(p_pos);
|
||||||
|
m_velocity = p_velocity;
|
||||||
|
//if (moveresult.collides) errorstream << "collision" << std::endl;
|
||||||
|
//if (moveresult.touching_ground) errorstream << "ground" << std::endl;
|
||||||
|
m_velocity += dtime * m_acceleration;
|
||||||
|
} else {
|
||||||
|
m_base_position += dtime * m_velocity + 0.5 * dtime
|
||||||
|
* dtime * m_acceleration;
|
||||||
|
m_velocity += dtime * m_acceleration;
|
||||||
|
}
|
||||||
|
|
||||||
|
//errorstream << this << " step: new_vel=(" << m_velocity.X << "," << m_velocity.Y << "," << m_velocity.Z << ")" << std::endl;
|
||||||
|
//errorstream << this << " step: new_pos=(" << m_base_position.X << "," << m_base_position.Y << "," << m_base_position.Z << ")" << std::endl;
|
||||||
|
|
||||||
|
if(m_registered){
|
||||||
|
lua_State *L = m_env->getLua();
|
||||||
|
scriptapi_luaentity_step(L, m_id, dtime);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(send_recommended == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// TODO: force send when acceleration changes enough?
|
||||||
|
float minchange = 0.2*BS;
|
||||||
|
if(m_last_sent_position_timer > 1.0){
|
||||||
|
minchange = 0.01*BS;
|
||||||
|
} else if(m_last_sent_position_timer > 0.2){
|
||||||
|
minchange = 0.05*BS;
|
||||||
|
}
|
||||||
|
float move_d = m_base_position.getDistanceFrom(m_last_sent_position);
|
||||||
|
move_d += m_last_sent_move_precision;
|
||||||
|
float vel_d = m_velocity.getDistanceFrom(m_last_sent_velocity);
|
||||||
|
if(move_d > minchange || vel_d > minchange ||
|
||||||
|
fabs(m_yaw - m_last_sent_yaw) > 1.0 ||
|
||||||
|
m_last_sent_position_timer > 10.0){
|
||||||
|
sendPosition(true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string LuaEntitySAO::getClientInitializationData()
|
||||||
|
{
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// version
|
||||||
|
writeU8(os, 0);
|
||||||
|
// pos
|
||||||
|
writeV3F1000(os, m_base_position);
|
||||||
|
// yaw
|
||||||
|
writeF1000(os, m_yaw);
|
||||||
|
// properties
|
||||||
|
std::ostringstream prop_os(std::ios::binary);
|
||||||
|
m_prop->serialize(prop_os);
|
||||||
|
os<<serializeLongString(prop_os.str());
|
||||||
|
// return result
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string LuaEntitySAO::getStaticData()
|
||||||
|
{
|
||||||
|
infostream<<__FUNCTION_NAME<<std::endl;
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// version
|
||||||
|
writeU8(os, 0);
|
||||||
|
// name
|
||||||
|
os<<serializeString(m_init_name);
|
||||||
|
// state
|
||||||
|
if(m_registered){
|
||||||
|
lua_State *L = m_env->getLua();
|
||||||
|
std::string state = scriptapi_luaentity_get_staticdata(L, m_id);
|
||||||
|
os<<serializeLongString(state);
|
||||||
|
} else {
|
||||||
|
os<<serializeLongString(m_init_state);
|
||||||
|
}
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaEntitySAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
|
||||||
|
{
|
||||||
|
if(!m_registered){
|
||||||
|
// Delete unknown LuaEntities when punched
|
||||||
|
m_removed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lua_State *L = m_env->getLua();
|
||||||
|
scriptapi_luaentity_punch(L, m_id, puncher, time_from_last_punch);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaEntitySAO::rightClick(ServerActiveObject *clicker)
|
||||||
|
{
|
||||||
|
if(!m_registered)
|
||||||
|
return;
|
||||||
|
lua_State *L = m_env->getLua();
|
||||||
|
scriptapi_luaentity_rightclick(L, m_id, clicker);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaEntitySAO::setPos(v3f pos)
|
||||||
|
{
|
||||||
|
m_base_position = pos;
|
||||||
|
sendPosition(false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaEntitySAO::moveTo(v3f pos, bool continuous)
|
||||||
|
{
|
||||||
|
m_base_position = pos;
|
||||||
|
if(!continuous)
|
||||||
|
sendPosition(true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
float LuaEntitySAO::getMinimumSavedMovement()
|
||||||
|
{
|
||||||
|
return 0.1 * BS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaEntitySAO::setVelocity(v3f velocity)
|
||||||
|
{
|
||||||
|
//errorstream << this << " Set velocity: (" << velocity.X << "," << velocity.Y << "," <<velocity.Z << ")" << std::endl;
|
||||||
|
m_velocity = velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
v3f LuaEntitySAO::getVelocity()
|
||||||
|
{
|
||||||
|
return m_velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaEntitySAO::setAcceleration(v3f acceleration)
|
||||||
|
{
|
||||||
|
m_acceleration = acceleration;
|
||||||
|
}
|
||||||
|
|
||||||
|
v3f LuaEntitySAO::getAcceleration()
|
||||||
|
{
|
||||||
|
return m_acceleration;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaEntitySAO::setYaw(float yaw)
|
||||||
|
{
|
||||||
|
m_yaw = yaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
float LuaEntitySAO::getYaw()
|
||||||
|
{
|
||||||
|
return m_yaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaEntitySAO::setTextureMod(const std::string &mod)
|
||||||
|
{
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// command (1 = set texture modification)
|
||||||
|
writeU8(os, AO_Message_type::SetTextureMod);
|
||||||
|
// parameters
|
||||||
|
os<<serializeString(mod);
|
||||||
|
// create message and add to list
|
||||||
|
ActiveObjectMessage aom(getId(), false, os.str());
|
||||||
|
m_messages_out.push_back(aom);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaEntitySAO::setSprite(v2s16 p, int num_frames, float framelength,
|
||||||
|
bool select_horiz_by_yawpitch)
|
||||||
|
{
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// command (2 = set sprite)
|
||||||
|
writeU8(os, AO_Message_type::SetSprite);
|
||||||
|
// parameters
|
||||||
|
writeV2S16(os, p);
|
||||||
|
writeU16(os, num_frames);
|
||||||
|
writeF1000(os, framelength);
|
||||||
|
writeU8(os, select_horiz_by_yawpitch);
|
||||||
|
// create message and add to list
|
||||||
|
ActiveObjectMessage aom(getId(), false, os.str());
|
||||||
|
m_messages_out.push_back(aom);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string LuaEntitySAO::getName()
|
||||||
|
{
|
||||||
|
return m_init_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
|
||||||
|
{
|
||||||
|
m_last_sent_move_precision = m_base_position.getDistanceFrom(
|
||||||
|
m_last_sent_position);
|
||||||
|
m_last_sent_position_timer = 0;
|
||||||
|
m_last_sent_yaw = m_yaw;
|
||||||
|
m_last_sent_position = m_base_position;
|
||||||
|
m_last_sent_velocity = m_velocity;
|
||||||
|
//m_last_sent_acceleration = m_acceleration;
|
||||||
|
|
||||||
|
float update_interval = m_env->getSendRecommendedInterval();
|
||||||
|
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// command (0 = update position)
|
||||||
|
writeU8(os, AO_Message_type::SetPosition);
|
||||||
|
|
||||||
|
// do_interpolate
|
||||||
|
writeU8(os, do_interpolate);
|
||||||
|
// pos
|
||||||
|
writeV3F1000(os, m_base_position);
|
||||||
|
// velocity
|
||||||
|
writeV3F1000(os, m_velocity);
|
||||||
|
// acceleration
|
||||||
|
writeV3F1000(os, m_acceleration);
|
||||||
|
// yaw
|
||||||
|
writeF1000(os, m_yaw);
|
||||||
|
// is_end_position (for interpolation)
|
||||||
|
writeU8(os, is_movement_end);
|
||||||
|
// update_interval (for interpolation)
|
||||||
|
writeF1000(os, update_interval);
|
||||||
|
|
||||||
|
// create message and add to list
|
||||||
|
ActiveObjectMessage aom(getId(), false, os.str());
|
||||||
|
m_messages_out.push_back(aom);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LuaEntitySAO::sendLinkMsg(ServerActiveObject* parent,v3f offset) {
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
writeU8(os, AO_Message_type::Link);
|
||||||
|
// parameters
|
||||||
|
writeU16(os, parent->getId());
|
||||||
|
writeV3F1000(os, offset);
|
||||||
|
// create message and add to list
|
||||||
|
ActiveObjectMessage aom(getId(), false, os.str());
|
||||||
|
m_messages_out.push_back(aom);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LuaEntitySAO::sendUnlinkMsg() {
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
writeU8(os, AO_Message_type::UnLink);
|
||||||
|
// create message and add to list
|
||||||
|
ActiveObjectMessage aom(getId(), false, os.str());
|
||||||
|
m_messages_out.push_back(aom);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
LuaEntitySAO proto_LuaEntitySAO(NULL, v3f(0,0,0), "_prototype", "");
|
||||||
80
src/content_sao_lua.h
Normal file
80
src/content_sao_lua.h
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2012 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_SAO_LUA_H_
|
||||||
|
#define CONTENT_SAO_LUA_H_
|
||||||
|
|
||||||
|
#include "content_sao.h"
|
||||||
|
#include "serverlinkableobject.h"
|
||||||
|
#include "scriptapi.h"
|
||||||
|
#include "luaentity_common.h"
|
||||||
|
|
||||||
|
class LuaEntitySAO : public ServerActiveObject, public ServerLinkableObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LuaEntitySAO(ServerEnvironment *env, v3f pos,
|
||||||
|
const std::string &name, const std::string &state);
|
||||||
|
~LuaEntitySAO();
|
||||||
|
u8 getType() const
|
||||||
|
{return ACTIVEOBJECT_TYPE_LUAENTITY;}
|
||||||
|
virtual void addedToEnvironment();
|
||||||
|
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
|
||||||
|
const std::string &data);
|
||||||
|
void step(float dtime, bool send_recommended);
|
||||||
|
std::string getClientInitializationData();
|
||||||
|
std::string getStaticData();
|
||||||
|
void punch(ServerActiveObject *puncher, float time_from_last_punch);
|
||||||
|
void rightClick(ServerActiveObject *clicker);
|
||||||
|
void setPos(v3f pos);
|
||||||
|
void moveTo(v3f pos, bool continuous);
|
||||||
|
float getMinimumSavedMovement();
|
||||||
|
/* LuaEntitySAO-specific */
|
||||||
|
void setVelocity(v3f velocity);
|
||||||
|
v3f getVelocity();
|
||||||
|
void setAcceleration(v3f acceleration);
|
||||||
|
v3f getAcceleration();
|
||||||
|
void setYaw(float yaw);
|
||||||
|
float getYaw();
|
||||||
|
void setTextureMod(const std::string &mod);
|
||||||
|
void setSprite(v2s16 p, int num_frames, float framelength,
|
||||||
|
bool select_horiz_by_yawpitch);
|
||||||
|
std::string getName();
|
||||||
|
bool sendLinkMsg(ServerActiveObject* parent,v3f offset);
|
||||||
|
bool sendUnlinkMsg();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void sendPosition(bool do_interpolate, bool is_movement_end);
|
||||||
|
|
||||||
|
std::string m_init_name;
|
||||||
|
std::string m_init_state;
|
||||||
|
bool m_registered;
|
||||||
|
struct LuaEntityProperties *m_prop;
|
||||||
|
|
||||||
|
v3f m_velocity;
|
||||||
|
v3f m_acceleration;
|
||||||
|
float m_yaw;
|
||||||
|
float m_last_sent_yaw;
|
||||||
|
v3f m_last_sent_position;
|
||||||
|
v3f m_last_sent_velocity;
|
||||||
|
float m_last_sent_position_timer;
|
||||||
|
float m_last_sent_move_precision;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* CONTENT_SAO_LUA_H_ */
|
||||||
522
src/content_sao_mobv2.cpp
Normal file
522
src/content_sao_mobv2.cpp
Normal file
@@ -0,0 +1,522 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2012 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_sao_mobv2.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
MobV2SAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
MobV2SAO::MobV2SAO(ServerEnvironment *env, v3f pos,
|
||||||
|
Settings *init_properties):
|
||||||
|
ServerActiveObject(env, pos),
|
||||||
|
m_move_type("ground_nodes"),
|
||||||
|
m_speed(0,0,0),
|
||||||
|
m_last_sent_position(0,0,0),
|
||||||
|
m_oldpos(0,0,0),
|
||||||
|
m_yaw(0),
|
||||||
|
m_counter1(0),
|
||||||
|
m_counter2(0),
|
||||||
|
m_age(0),
|
||||||
|
m_touching_ground(false),
|
||||||
|
m_hp(10),
|
||||||
|
m_walk_around(false),
|
||||||
|
m_walk_around_timer(0),
|
||||||
|
m_next_pos_exists(false),
|
||||||
|
m_shoot_reload_timer(0),
|
||||||
|
m_shooting(false),
|
||||||
|
m_shooting_timer(0),
|
||||||
|
m_falling(false),
|
||||||
|
m_disturb_timer(100000),
|
||||||
|
m_random_disturb_timer(0),
|
||||||
|
m_shoot_y(0)
|
||||||
|
{
|
||||||
|
ServerActiveObject::registerType(getType(), create);
|
||||||
|
|
||||||
|
m_properties = new Settings();
|
||||||
|
if(init_properties)
|
||||||
|
m_properties->update(*init_properties);
|
||||||
|
|
||||||
|
m_properties->setV3F("pos", pos);
|
||||||
|
|
||||||
|
setPropertyDefaults();
|
||||||
|
readProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
MobV2SAO::~MobV2SAO()
|
||||||
|
{
|
||||||
|
delete m_properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerActiveObject* MobV2SAO::create(ServerEnvironment *env, v3f pos,
|
||||||
|
const std::string &data)
|
||||||
|
{
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
Settings properties;
|
||||||
|
properties.parseConfigLines(is, "MobArgsEnd");
|
||||||
|
MobV2SAO *o = new MobV2SAO(env, pos, &properties);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MobV2SAO::getStaticData()
|
||||||
|
{
|
||||||
|
updateProperties();
|
||||||
|
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
m_properties->writeLines(os);
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MobV2SAO::getClientInitializationData()
|
||||||
|
{
|
||||||
|
//infostream<<__FUNCTION_NAME<<std::endl;
|
||||||
|
|
||||||
|
updateProperties();
|
||||||
|
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
|
||||||
|
// version
|
||||||
|
writeU8(os, 0);
|
||||||
|
|
||||||
|
Settings client_properties;
|
||||||
|
|
||||||
|
/*client_properties.set("version", "0");
|
||||||
|
client_properties.updateValue(*m_properties, "pos");
|
||||||
|
client_properties.updateValue(*m_properties, "yaw");
|
||||||
|
client_properties.updateValue(*m_properties, "hp");*/
|
||||||
|
|
||||||
|
// Just send everything for simplicity
|
||||||
|
client_properties.update(*m_properties);
|
||||||
|
|
||||||
|
std::ostringstream os2(std::ios::binary);
|
||||||
|
client_properties.writeLines(os2);
|
||||||
|
compressZlib(os2.str(), os);
|
||||||
|
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MobV2SAO::step(float dtime, bool send_recommended)
|
||||||
|
{
|
||||||
|
ScopeProfiler sp2(g_profiler, "MobV2SAO::step avg", SPT_AVG);
|
||||||
|
|
||||||
|
assert(m_env);
|
||||||
|
Map *map = &m_env->getMap();
|
||||||
|
|
||||||
|
m_age += dtime;
|
||||||
|
|
||||||
|
if(m_die_age >= 0.0 && m_age >= m_die_age){
|
||||||
|
m_removed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_random_disturb_timer += dtime;
|
||||||
|
if(m_random_disturb_timer >= 5.0)
|
||||||
|
{
|
||||||
|
m_random_disturb_timer = 0;
|
||||||
|
// Check connected players
|
||||||
|
core::list<Player*> players = m_env->getPlayers(true);
|
||||||
|
core::list<Player*>::Iterator i;
|
||||||
|
for(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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Player *disturbing_player =
|
||||||
|
m_env->getPlayer(m_disturbing_player.c_str());
|
||||||
|
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;
|
||||||
|
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_shooting_timer -= dtime;
|
||||||
|
if(m_shooting_timer <= 0.0 && m_shooting){
|
||||||
|
m_shooting = false;
|
||||||
|
|
||||||
|
std::string shoot_type = m_properties->get("shoot_type");
|
||||||
|
v3f shoot_pos(0,0,0);
|
||||||
|
shoot_pos.Y += m_properties->getFloat("shoot_y") * BS;
|
||||||
|
if(shoot_type == "fireball"){
|
||||||
|
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 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.setFloat("hp", 1000);
|
||||||
|
properties.set("lock_full_brightness", "true");
|
||||||
|
properties.set("player_hit_damage", "9");
|
||||||
|
properties.set("player_hit_distance", "2");
|
||||||
|
properties.set("player_hit_interval", "1");
|
||||||
|
ServerActiveObject *obj = new MobV2SAO(m_env,
|
||||||
|
pos, &properties);
|
||||||
|
//m_env->addActiveObjectAsStatic(obj);
|
||||||
|
m_env->addActiveObject(obj);
|
||||||
|
} else {
|
||||||
|
infostream<<__FUNCTION_NAME<<": Mob id="<<m_id
|
||||||
|
<<": Unknown shoot_type="<<shoot_type
|
||||||
|
<<std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_shoot_reload_timer += dtime;
|
||||||
|
|
||||||
|
float reload_time = 15.0;
|
||||||
|
if(m_disturb_timer <= 15.0)
|
||||||
|
reload_time = 3.0;
|
||||||
|
|
||||||
|
bool shoot_without_player = false;
|
||||||
|
if(m_properties->getBool("mindless_rage"))
|
||||||
|
shoot_without_player = true;
|
||||||
|
|
||||||
|
if(!m_shooting && m_shoot_reload_timer >= reload_time &&
|
||||||
|
!m_next_pos_exists &&
|
||||||
|
(m_disturb_timer <= 60.0 || shoot_without_player))
|
||||||
|
{
|
||||||
|
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, AO_Message_type::Shoot);
|
||||||
|
// 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_move_type == "ground_nodes")
|
||||||
|
{
|
||||||
|
if(!m_shooting){
|
||||||
|
m_walk_around_timer -= dtime;
|
||||||
|
if(m_walk_around_timer <= 0.0){
|
||||||
|
m_walk_around = !m_walk_around;
|
||||||
|
if(m_walk_around)
|
||||||
|
m_walk_around_timer = 0.1*myrand_range(10,50);
|
||||||
|
else
|
||||||
|
m_walk_around_timer = 0.1*myrand_range(30,70);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move */
|
||||||
|
if(m_next_pos_exists){
|
||||||
|
v3f pos_f = m_base_position;
|
||||||
|
v3f next_pos_f = intToFloat(m_next_pos_i, BS);
|
||||||
|
|
||||||
|
v3f v = next_pos_f - pos_f;
|
||||||
|
m_yaw = atan2(v.Z, v.X) / PI * 180;
|
||||||
|
|
||||||
|
v3f diff = next_pos_f - pos_f;
|
||||||
|
v3f dir = diff;
|
||||||
|
dir.normalize();
|
||||||
|
float speed = BS * 0.5;
|
||||||
|
if(m_falling)
|
||||||
|
speed = BS * 3.0;
|
||||||
|
dir *= dtime * speed;
|
||||||
|
bool arrived = false;
|
||||||
|
if(dir.getLength() > diff.getLength()){
|
||||||
|
dir = diff;
|
||||||
|
arrived = true;
|
||||||
|
}
|
||||||
|
pos_f += dir;
|
||||||
|
m_base_position = pos_f;
|
||||||
|
|
||||||
|
if((pos_f - next_pos_f).getLength() < 0.1 || arrived){
|
||||||
|
m_next_pos_exists = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v3s16 pos_i = floatToInt(m_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!m_next_pos_exists){
|
||||||
|
/* Check whether to drop down */
|
||||||
|
if(checkFreePosition(map,
|
||||||
|
pos_i + pos_size_off + v3s16(0,-1,0), size_blocks)){
|
||||||
|
m_next_pos_i = pos_i + v3s16(0,-1,0);
|
||||||
|
m_next_pos_exists = true;
|
||||||
|
m_falling = true;
|
||||||
|
} else {
|
||||||
|
m_falling = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_walk_around)
|
||||||
|
{
|
||||||
|
if(!m_next_pos_exists){
|
||||||
|
/* Find some position where to go next */
|
||||||
|
v3s16 dps[3*3*3];
|
||||||
|
int num_dps = 0;
|
||||||
|
for(int dx=-1; dx<=1; dx++)
|
||||||
|
for(int dy=-1; dy<=1; dy++)
|
||||||
|
for(int dz=-1; dz<=1; dz++){
|
||||||
|
if(dx == 0 && dy == 0)
|
||||||
|
continue;
|
||||||
|
if(dx != 0 && dz != 0 && dy != 0)
|
||||||
|
continue;
|
||||||
|
dps[num_dps++] = v3s16(dx,dy,dz);
|
||||||
|
}
|
||||||
|
u32 order[3*3*3];
|
||||||
|
get_random_u32_array(order, num_dps);
|
||||||
|
for(int i=0; i<num_dps; i++){
|
||||||
|
v3s16 p = dps[order[i]] + pos_i;
|
||||||
|
bool is_free = checkFreeAndWalkablePosition(map,
|
||||||
|
p + pos_size_off, size_blocks);
|
||||||
|
if(!is_free)
|
||||||
|
continue;
|
||||||
|
m_next_pos_i = p;
|
||||||
|
m_next_pos_exists = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(m_move_type == "constant_speed")
|
||||||
|
{
|
||||||
|
m_base_position += m_speed * dtime;
|
||||||
|
|
||||||
|
v3s16 pos_i = floatToInt(m_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){
|
||||||
|
explodeSquare(map, pos_i, v3s16(3,3,3));
|
||||||
|
m_removed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errorstream<<"MobV2SAO::step(): id="<<m_id<<" unknown move_type=\""
|
||||||
|
<<m_move_type<<"\""<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(send_recommended == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(m_base_position.getDistanceFrom(m_last_sent_position) > 0.05*BS)
|
||||||
|
{
|
||||||
|
sendPosition();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MobV2SAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
|
||||||
|
{
|
||||||
|
if(!puncher)
|
||||||
|
return;
|
||||||
|
|
||||||
|
v3f dir = (getBasePosition() - puncher->getBasePosition()).normalize();
|
||||||
|
|
||||||
|
// A quick hack; SAO description is player name for player
|
||||||
|
std::string playername = puncher->getDescription();
|
||||||
|
|
||||||
|
Map *map = &m_env->getMap();
|
||||||
|
|
||||||
|
actionstream<<playername<<" punches mob id="<<m_id
|
||||||
|
<<" at "<<PP(m_base_position/BS)<<std::endl;
|
||||||
|
|
||||||
|
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 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();
|
||||||
|
|
||||||
|
|
||||||
|
// "Material" properties of the MobV2
|
||||||
|
MaterialProperties mp;
|
||||||
|
mp.diggability = DIGGABLE_NORMAL;
|
||||||
|
mp.crackiness = -1.0;
|
||||||
|
mp.cuttability = 1.0;
|
||||||
|
|
||||||
|
ToolDiggingProperties tp;
|
||||||
|
puncher->getWieldDiggingProperties(&tp);
|
||||||
|
|
||||||
|
HittingProperties hitprop = getHittingProperties(&mp, &tp,
|
||||||
|
time_from_last_punch);
|
||||||
|
|
||||||
|
doDamage(hitprop.hp);
|
||||||
|
puncher->damageWieldedItem(hitprop.wear);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MobV2SAO::isPeaceful()
|
||||||
|
{
|
||||||
|
return m_properties->getBool("is_peaceful");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MobV2SAO::sendPosition()
|
||||||
|
{
|
||||||
|
m_last_sent_position = m_base_position;
|
||||||
|
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// command (0 = update position)
|
||||||
|
writeU8(os, AO_Message_type::SetPosition);
|
||||||
|
// 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("is_peaceful", "false");
|
||||||
|
m_properties->setDefault("move_type", "ground_nodes");
|
||||||
|
m_properties->setDefault("speed", "(0,0,0)");
|
||||||
|
m_properties->setDefault("age", "0");
|
||||||
|
m_properties->setDefault("yaw", "0");
|
||||||
|
m_properties->setDefault("pos", "(0,0,0)");
|
||||||
|
m_properties->setDefault("hp", "0");
|
||||||
|
m_properties->setDefault("die_age", "-1");
|
||||||
|
m_properties->setDefault("size", "(1,2)");
|
||||||
|
m_properties->setDefault("shoot_type", "fireball");
|
||||||
|
m_properties->setDefault("shoot_y", "0");
|
||||||
|
m_properties->setDefault("mindless_rage", "false");
|
||||||
|
}
|
||||||
|
void MobV2SAO::readProperties()
|
||||||
|
{
|
||||||
|
m_move_type = m_properties->get("move_type");
|
||||||
|
m_speed = m_properties->getV3F("speed");
|
||||||
|
m_age = m_properties->getFloat("age");
|
||||||
|
m_yaw = m_properties->getFloat("yaw");
|
||||||
|
m_base_position = m_properties->getV3F("pos");
|
||||||
|
m_hp = m_properties->getS32("hp");
|
||||||
|
m_die_age = m_properties->getFloat("die_age");
|
||||||
|
m_size = m_properties->getV2F("size");
|
||||||
|
}
|
||||||
|
void MobV2SAO::updateProperties()
|
||||||
|
{
|
||||||
|
m_properties->set("move_type", m_move_type);
|
||||||
|
m_properties->setV3F("speed", m_speed);
|
||||||
|
m_properties->setFloat("age", m_age);
|
||||||
|
m_properties->setFloat("yaw", m_yaw);
|
||||||
|
m_properties->setV3F("pos", m_base_position);
|
||||||
|
m_properties->setS32("hp", m_hp);
|
||||||
|
m_properties->setFloat("die_age", m_die_age);
|
||||||
|
m_properties->setV2F("size", m_size);
|
||||||
|
|
||||||
|
m_properties->setS32("version", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MobV2SAO::doDamage(u16 d)
|
||||||
|
{
|
||||||
|
infostream<<"MobV2 hp="<<m_hp<<" damage="<<d<<std::endl;
|
||||||
|
|
||||||
|
if(d < m_hp)
|
||||||
|
{
|
||||||
|
m_hp -= d;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
actionstream<<"A "<<(isPeaceful()?"peaceful":"non-peaceful")
|
||||||
|
<<" 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, AO_Message_type::TakeDamage);
|
||||||
|
// amount
|
||||||
|
writeU16(os, d);
|
||||||
|
// create message and add to list
|
||||||
|
ActiveObjectMessage aom(getId(), false, os.str());
|
||||||
|
m_messages_out.push_back(aom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
MobV2SAO proto_MobV2SAO(NULL, v3f(0,0,0), NULL);
|
||||||
76
src/content_sao_mobv2.h
Normal file
76
src/content_sao_mobv2.h
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2012 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_SAO_MOBV2_H_
|
||||||
|
#define CONTENT_SAO_MOBV2_H_
|
||||||
|
|
||||||
|
#include "content_sao.h"
|
||||||
|
|
||||||
|
class MobV2SAO : public ServerActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MobV2SAO(ServerEnvironment *env, v3f pos,
|
||||||
|
Settings *init_properties);
|
||||||
|
virtual ~MobV2SAO();
|
||||||
|
u8 getType() const
|
||||||
|
{return ACTIVEOBJECT_TYPE_MOBV2;}
|
||||||
|
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
|
||||||
|
const std::string &data);
|
||||||
|
std::string getStaticData();
|
||||||
|
std::string getClientInitializationData();
|
||||||
|
void step(float dtime, bool send_recommended);
|
||||||
|
void punch(ServerActiveObject *puncher, float time_from_last_punch);
|
||||||
|
bool isPeaceful();
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* CONTENT_SAO_MOBV2_H_ */
|
||||||
314
src/content_sao_oerkki1.cpp
Normal file
314
src/content_sao_oerkki1.cpp
Normal file
@@ -0,0 +1,314 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2012 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_sao_oerkki1.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Oerkki1SAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
Oerkki1SAO::Oerkki1SAO(ServerEnvironment *env, v3f pos):
|
||||||
|
ServerActiveObject(env, pos),
|
||||||
|
m_is_active(false),
|
||||||
|
m_speed_f(0,0,0)
|
||||||
|
{
|
||||||
|
ServerActiveObject::registerType(getType(), create);
|
||||||
|
|
||||||
|
m_oldpos = v3f(0,0,0);
|
||||||
|
m_last_sent_position = v3f(0,0,0);
|
||||||
|
m_yaw = 0;
|
||||||
|
m_counter1 = 0;
|
||||||
|
m_counter2 = 0;
|
||||||
|
m_age = 0;
|
||||||
|
m_touching_ground = false;
|
||||||
|
m_hp = 20;
|
||||||
|
m_after_jump_timer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerActiveObject* Oerkki1SAO::create(ServerEnvironment *env, v3f pos,
|
||||||
|
const std::string &data)
|
||||||
|
{
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// read version
|
||||||
|
u8 version = readU8(is);
|
||||||
|
// read hp
|
||||||
|
u8 hp = readU8(is);
|
||||||
|
// check if version is supported
|
||||||
|
if(version != 0)
|
||||||
|
return NULL;
|
||||||
|
Oerkki1SAO *o = new Oerkki1SAO(env, pos);
|
||||||
|
o->m_hp = hp;
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oerkki1SAO::step(float dtime, bool send_recommended)
|
||||||
|
{
|
||||||
|
ScopeProfiler sp2(g_profiler, "Oerkki1SAO::step avg", SPT_AVG);
|
||||||
|
|
||||||
|
assert(m_env);
|
||||||
|
|
||||||
|
if(m_is_active == false)
|
||||||
|
{
|
||||||
|
if(m_inactive_interval.step(dtime, 0.5)==false)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
The AI
|
||||||
|
*/
|
||||||
|
|
||||||
|
m_age += dtime;
|
||||||
|
if(m_age > 120)
|
||||||
|
{
|
||||||
|
// Die
|
||||||
|
m_removed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_after_jump_timer -= dtime;
|
||||||
|
|
||||||
|
v3f old_speed = m_speed_f;
|
||||||
|
|
||||||
|
// Apply gravity
|
||||||
|
m_speed_f.Y -= dtime*9.81*BS;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Move around if some player is close
|
||||||
|
*/
|
||||||
|
bool player_is_close = false;
|
||||||
|
bool player_is_too_close = false;
|
||||||
|
v3f near_player_pos;
|
||||||
|
// Check connected players
|
||||||
|
core::list<Player*> players = m_env->getPlayers(true);
|
||||||
|
core::list<Player*>::Iterator i;
|
||||||
|
for(i = players.begin();
|
||||||
|
i != players.end(); i++)
|
||||||
|
{
|
||||||
|
Player *player = *i;
|
||||||
|
v3f playerpos = player->getPosition();
|
||||||
|
f32 dist = m_base_position.getDistanceFrom(playerpos);
|
||||||
|
if(dist < BS*0.6)
|
||||||
|
{
|
||||||
|
m_removed = true;
|
||||||
|
return;
|
||||||
|
player_is_too_close = true;
|
||||||
|
near_player_pos = playerpos;
|
||||||
|
}
|
||||||
|
else if(dist < BS*15.0 && !player_is_too_close)
|
||||||
|
{
|
||||||
|
player_is_close = true;
|
||||||
|
near_player_pos = playerpos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_is_active = player_is_close;
|
||||||
|
|
||||||
|
v3f target_speed = m_speed_f;
|
||||||
|
|
||||||
|
if(!player_is_close)
|
||||||
|
{
|
||||||
|
target_speed = v3f(0,0,0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Move around
|
||||||
|
|
||||||
|
v3f ndir = near_player_pos - m_base_position;
|
||||||
|
ndir.Y = 0;
|
||||||
|
ndir.normalize();
|
||||||
|
|
||||||
|
f32 nyaw = 180./PI*atan2(ndir.Z,ndir.X);
|
||||||
|
if(nyaw < m_yaw - 180)
|
||||||
|
nyaw += 360;
|
||||||
|
else if(nyaw > m_yaw + 180)
|
||||||
|
nyaw -= 360;
|
||||||
|
m_yaw = 0.95*m_yaw + 0.05*nyaw;
|
||||||
|
m_yaw = wrapDegrees(m_yaw);
|
||||||
|
|
||||||
|
f32 speed = 2*BS;
|
||||||
|
|
||||||
|
if((m_touching_ground || m_after_jump_timer > 0.0)
|
||||||
|
&& !player_is_too_close)
|
||||||
|
{
|
||||||
|
v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
|
||||||
|
target_speed.X = speed * dir.X;
|
||||||
|
target_speed.Z = speed * dir.Z;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_touching_ground && (m_oldpos - m_base_position).getLength()
|
||||||
|
< dtime*speed/2)
|
||||||
|
{
|
||||||
|
m_counter1 -= dtime;
|
||||||
|
if(m_counter1 < 0.0)
|
||||||
|
{
|
||||||
|
m_counter1 += 0.2;
|
||||||
|
// Jump
|
||||||
|
target_speed.Y = 5.0*BS;
|
||||||
|
m_after_jump_timer = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
m_counter2 -= dtime;
|
||||||
|
if(m_counter2 < 0.0)
|
||||||
|
{
|
||||||
|
m_counter2 += (float)(myrand()%100)/100*3.0;
|
||||||
|
//m_yaw += ((float)(myrand()%200)-100)/100*180;
|
||||||
|
m_yaw += ((float)(myrand()%200)-100)/100*90;
|
||||||
|
m_yaw = wrapDegrees(m_yaw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if((m_speed_f - target_speed).getLength() > BS*4 || player_is_too_close)
|
||||||
|
accelerate_xz(m_speed_f, target_speed, dtime*BS*8);
|
||||||
|
else
|
||||||
|
accelerate_xz(m_speed_f, target_speed, dtime*BS*4);
|
||||||
|
|
||||||
|
m_oldpos = m_base_position;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Move it, with collision detection
|
||||||
|
*/
|
||||||
|
|
||||||
|
core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*5./3.,BS/3.);
|
||||||
|
collisionMoveResult moveresult;
|
||||||
|
// Maximum movement without glitches
|
||||||
|
f32 pos_max_d = BS*0.25;
|
||||||
|
/*// Limit speed
|
||||||
|
if(m_speed_f.getLength()*dtime > pos_max_d)
|
||||||
|
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);*/
|
||||||
|
v3f pos_f = getBasePosition();
|
||||||
|
v3f pos_f_old = pos_f;
|
||||||
|
IGameDef *gamedef = m_env->getGameDef();
|
||||||
|
moveresult = collisionMovePrecise(&m_env->getMap(), gamedef,
|
||||||
|
pos_max_d, box, dtime, pos_f, m_speed_f);
|
||||||
|
m_touching_ground = moveresult.touching_ground;
|
||||||
|
|
||||||
|
// Do collision damage
|
||||||
|
float tolerance = BS*30;
|
||||||
|
float factor = BS*0.5;
|
||||||
|
v3f speed_diff = old_speed - m_speed_f;
|
||||||
|
// Increase effect in X and Z
|
||||||
|
speed_diff.X *= 2;
|
||||||
|
speed_diff.Z *= 2;
|
||||||
|
float vel = speed_diff.getLength();
|
||||||
|
if(vel > tolerance)
|
||||||
|
{
|
||||||
|
f32 damage_f = (vel - tolerance)/BS*factor;
|
||||||
|
u16 damage = (u16)(damage_f+0.5);
|
||||||
|
doDamage(damage);
|
||||||
|
}
|
||||||
|
|
||||||
|
setBasePosition(pos_f);
|
||||||
|
|
||||||
|
if(send_recommended == false && m_speed_f.getLength() < 3.0*BS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
|
||||||
|
{
|
||||||
|
m_last_sent_position = pos_f;
|
||||||
|
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// command (0 = update position)
|
||||||
|
writeU8(os, AO_Message_type::SetPosition);
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Oerkki1SAO::getClientInitializationData()
|
||||||
|
{
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// version
|
||||||
|
writeU8(os, 0);
|
||||||
|
// pos
|
||||||
|
writeV3F1000(os, m_base_position);
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Oerkki1SAO::getStaticData()
|
||||||
|
{
|
||||||
|
//infostream<<__FUNCTION_NAME<<std::endl;
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// version
|
||||||
|
writeU8(os, 0);
|
||||||
|
// hp
|
||||||
|
writeU8(os, m_hp);
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oerkki1SAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
|
||||||
|
{
|
||||||
|
if(!puncher)
|
||||||
|
return;
|
||||||
|
|
||||||
|
v3f dir = (getBasePosition() - puncher->getBasePosition()).normalize();
|
||||||
|
m_speed_f += dir*12*BS;
|
||||||
|
|
||||||
|
// "Material" properties of an oerkki
|
||||||
|
MaterialProperties mp;
|
||||||
|
mp.diggability = DIGGABLE_NORMAL;
|
||||||
|
mp.crackiness = -1.0;
|
||||||
|
mp.cuttability = 1.0;
|
||||||
|
|
||||||
|
ToolDiggingProperties tp;
|
||||||
|
puncher->getWieldDiggingProperties(&tp);
|
||||||
|
|
||||||
|
HittingProperties hitprop = getHittingProperties(&mp, &tp,
|
||||||
|
time_from_last_punch);
|
||||||
|
|
||||||
|
doDamage(hitprop.hp);
|
||||||
|
puncher->damageWieldedItem(hitprop.wear);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oerkki1SAO::doDamage(u16 d)
|
||||||
|
{
|
||||||
|
infostream<<"oerkki damage: "<<d<<std::endl;
|
||||||
|
|
||||||
|
if(d < m_hp)
|
||||||
|
{
|
||||||
|
m_hp -= d;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Die
|
||||||
|
m_hp = 0;
|
||||||
|
m_removed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// command (1 = damage)
|
||||||
|
writeU8(os, AO_Message_type::TakeDamage);
|
||||||
|
// amount
|
||||||
|
writeU8(os, d);
|
||||||
|
// create message and add to list
|
||||||
|
ActiveObjectMessage aom(getId(), false, os.str());
|
||||||
|
m_messages_out.push_back(aom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
Oerkki1SAO proto_Oerkki1SAO(NULL, v3f(0,0,0));
|
||||||
55
src/content_sao_oerkki1.h
Normal file
55
src/content_sao_oerkki1.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2012 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_SAO_OERKKI1_H_
|
||||||
|
#define CONTENT_SAO_OERKKI1_H_
|
||||||
|
|
||||||
|
#include "content_sao.h"
|
||||||
|
|
||||||
|
class Oerkki1SAO : public ServerActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Oerkki1SAO(ServerEnvironment *env, v3f pos);
|
||||||
|
u8 getType() const
|
||||||
|
{return ACTIVEOBJECT_TYPE_OERKKI1;}
|
||||||
|
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
|
||||||
|
const std::string &data);
|
||||||
|
void step(float dtime, bool send_recommended);
|
||||||
|
std::string getClientInitializationData();
|
||||||
|
std::string getStaticData();
|
||||||
|
void punch(ServerActiveObject *puncher, float time_from_last_punch);
|
||||||
|
bool isPeaceful(){return false;}
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* CONTENT_SAO_OERKKI1_H_ */
|
||||||
212
src/content_sao_rat.cpp
Normal file
212
src/content_sao_rat.cpp
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2012 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_sao_rat.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
RatSAO
|
||||||
|
*/
|
||||||
|
RatSAO::RatSAO(ServerEnvironment *env, v3f pos):
|
||||||
|
ServerActiveObject(env, pos),
|
||||||
|
m_is_active(false),
|
||||||
|
m_speed_f(0,0,0)
|
||||||
|
{
|
||||||
|
ServerActiveObject::registerType(getType(), create);
|
||||||
|
|
||||||
|
m_oldpos = v3f(0,0,0);
|
||||||
|
m_last_sent_position = v3f(0,0,0);
|
||||||
|
m_yaw = myrand_range(0,PI*2);
|
||||||
|
m_counter1 = 0;
|
||||||
|
m_counter2 = 0;
|
||||||
|
m_age = 0;
|
||||||
|
m_touching_ground = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerActiveObject* RatSAO::create(ServerEnvironment *env, v3f pos,
|
||||||
|
const std::string &data)
|
||||||
|
{
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
char buf[1];
|
||||||
|
// read version
|
||||||
|
is.read(buf, 1);
|
||||||
|
u8 version = buf[0];
|
||||||
|
// check if version is supported
|
||||||
|
if(version != 0)
|
||||||
|
return NULL;
|
||||||
|
return new RatSAO(env, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RatSAO::step(float dtime, bool send_recommended)
|
||||||
|
{
|
||||||
|
ScopeProfiler sp2(g_profiler, "RatSAO::step avg", SPT_AVG);
|
||||||
|
|
||||||
|
assert(m_env);
|
||||||
|
|
||||||
|
if(m_is_active == false)
|
||||||
|
{
|
||||||
|
if(m_inactive_interval.step(dtime, 0.5)==false)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
The AI
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*m_age += dtime;
|
||||||
|
if(m_age > 60)
|
||||||
|
{
|
||||||
|
// Die
|
||||||
|
m_removed = true;
|
||||||
|
return;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// Apply gravity
|
||||||
|
m_speed_f.Y -= dtime*9.81*BS;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Move around if some player is close
|
||||||
|
*/
|
||||||
|
bool player_is_close = false;
|
||||||
|
// Check connected players
|
||||||
|
core::list<Player*> players = m_env->getPlayers(true);
|
||||||
|
core::list<Player*>::Iterator i;
|
||||||
|
for(i = players.begin();
|
||||||
|
i != players.end(); i++)
|
||||||
|
{
|
||||||
|
Player *player = *i;
|
||||||
|
v3f playerpos = player->getPosition();
|
||||||
|
if(m_base_position.getDistanceFrom(playerpos) < BS*10.0)
|
||||||
|
{
|
||||||
|
player_is_close = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_is_active = player_is_close;
|
||||||
|
|
||||||
|
if(player_is_close == false)
|
||||||
|
{
|
||||||
|
m_speed_f.X = 0;
|
||||||
|
m_speed_f.Z = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Move around
|
||||||
|
v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
|
||||||
|
f32 speed = 2*BS;
|
||||||
|
m_speed_f.X = speed * dir.X;
|
||||||
|
m_speed_f.Z = speed * dir.Z;
|
||||||
|
|
||||||
|
if(m_touching_ground && (m_oldpos - m_base_position).getLength()
|
||||||
|
< dtime*speed/2)
|
||||||
|
{
|
||||||
|
m_counter1 -= dtime;
|
||||||
|
if(m_counter1 < 0.0)
|
||||||
|
{
|
||||||
|
m_counter1 += 1.0;
|
||||||
|
m_speed_f.Y = 5.0*BS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
m_counter2 -= dtime;
|
||||||
|
if(m_counter2 < 0.0)
|
||||||
|
{
|
||||||
|
m_counter2 += (float)(myrand()%100)/100*3.0;
|
||||||
|
m_yaw += ((float)(myrand()%200)-100)/100*180;
|
||||||
|
m_yaw = wrapDegrees(m_yaw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_oldpos = m_base_position;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Move it, with collision detection
|
||||||
|
*/
|
||||||
|
|
||||||
|
core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.);
|
||||||
|
collisionMoveResult moveresult;
|
||||||
|
// Maximum movement without glitches
|
||||||
|
f32 pos_max_d = BS*0.25;
|
||||||
|
// Limit speed
|
||||||
|
if(m_speed_f.getLength()*dtime > pos_max_d)
|
||||||
|
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
|
||||||
|
v3f pos_f = getBasePosition();
|
||||||
|
v3f pos_f_old = pos_f;
|
||||||
|
IGameDef *gamedef = m_env->getGameDef();
|
||||||
|
moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
|
||||||
|
pos_max_d, box, dtime, pos_f, m_speed_f);
|
||||||
|
m_touching_ground = moveresult.touching_ground;
|
||||||
|
|
||||||
|
setBasePosition(pos_f);
|
||||||
|
|
||||||
|
if(send_recommended == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
|
||||||
|
{
|
||||||
|
m_last_sent_position = pos_f;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string RatSAO::getClientInitializationData()
|
||||||
|
{
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// version
|
||||||
|
writeU8(os, 0);
|
||||||
|
// pos
|
||||||
|
writeV3F1000(os, m_base_position);
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string RatSAO::getStaticData()
|
||||||
|
{
|
||||||
|
//infostream<<__FUNCTION_NAME<<std::endl;
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// version
|
||||||
|
writeU8(os, 0);
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RatSAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
|
||||||
|
{
|
||||||
|
std::istringstream is("CraftItem rat 1", std::ios_base::binary);
|
||||||
|
IGameDef *gamedef = m_env->getGameDef();
|
||||||
|
InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
|
||||||
|
bool fits = puncher->addToInventory(item);
|
||||||
|
if(fits)
|
||||||
|
m_removed = true;
|
||||||
|
else
|
||||||
|
delete item;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
RatSAO proto_RatSAO(NULL, v3f(0,0,0));
|
||||||
50
src/content_sao_rat.h
Normal file
50
src/content_sao_rat.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2012 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_SAO_RAT_H_
|
||||||
|
#define CONTENT_SAO_RAT_H_
|
||||||
|
|
||||||
|
#include "content_sao.h"
|
||||||
|
|
||||||
|
class RatSAO : public ServerActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RatSAO(ServerEnvironment *env, v3f pos);
|
||||||
|
u8 getType() const
|
||||||
|
{return ACTIVEOBJECT_TYPE_RAT;}
|
||||||
|
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
|
||||||
|
const std::string &data);
|
||||||
|
void step(float dtime, bool send_recommended);
|
||||||
|
std::string getClientInitializationData();
|
||||||
|
std::string getStaticData();
|
||||||
|
void punch(ServerActiveObject *puncher, float time_from_last_punch);
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* CONTENT_SAO_RAT_H_ */
|
||||||
90
src/content_sao_test.cpp
Normal file
90
src/content_sao_test.cpp
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2012 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_sao.h"
|
||||||
|
|
||||||
|
|
||||||
|
class TestSAO : public ServerActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TestSAO(ServerEnvironment *env, v3f pos);
|
||||||
|
u8 getType() const
|
||||||
|
{return ACTIVEOBJECT_TYPE_TEST;}
|
||||||
|
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
|
||||||
|
const std::string &data);
|
||||||
|
void step(float dtime, bool send_recommended);
|
||||||
|
private:
|
||||||
|
float m_timer1;
|
||||||
|
float m_age;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
TestSAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
TestSAO::TestSAO(ServerEnvironment *env, v3f pos):
|
||||||
|
ServerActiveObject(env, pos),
|
||||||
|
m_timer1(0),
|
||||||
|
m_age(0)
|
||||||
|
{
|
||||||
|
ServerActiveObject::registerType(getType(), create);
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerActiveObject* TestSAO::create(ServerEnvironment *env, v3f pos,
|
||||||
|
const std::string &data)
|
||||||
|
{
|
||||||
|
return new TestSAO(env, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSAO::step(float dtime, bool send_recommended)
|
||||||
|
{
|
||||||
|
m_age += dtime;
|
||||||
|
if(m_age > 10)
|
||||||
|
{
|
||||||
|
m_removed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_base_position.Y += dtime * BS * 2;
|
||||||
|
if(m_base_position.Y > 8*BS)
|
||||||
|
m_base_position.Y = 2*BS;
|
||||||
|
|
||||||
|
if(send_recommended == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_timer1 -= dtime;
|
||||||
|
if(m_timer1 < 0.0)
|
||||||
|
{
|
||||||
|
m_timer1 += 0.125;
|
||||||
|
|
||||||
|
std::string data;
|
||||||
|
|
||||||
|
data += itos(AO_Message_type::SetPosition); // 0 = position
|
||||||
|
data += " ";
|
||||||
|
data += itos(m_base_position.X);
|
||||||
|
data += " ";
|
||||||
|
data += itos(m_base_position.Y);
|
||||||
|
data += " ";
|
||||||
|
data += itos(m_base_position.Z);
|
||||||
|
|
||||||
|
ActiveObjectMessage aom(getId(), false, data);
|
||||||
|
m_messages_out.push_back(aom);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -765,6 +765,21 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
|
|||||||
abmhandler.apply(block);
|
abmhandler.apply(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
core::list<MapNode> ServerEnvironment::getNodesInsideRadius(v3s16 pos, float radius)
|
||||||
|
{
|
||||||
|
core::list<MapNode> nodes;
|
||||||
|
for (int i = pos.X - radius; i < pos.X + radius; i ++)
|
||||||
|
for (int j = pos.Y - radius; j < pos.Y + radius; j ++)
|
||||||
|
for (int k = pos.Z - radius; k < pos.Z + radius; k ++) {
|
||||||
|
v3s16 current_pos = v3s16(i,j,k);
|
||||||
|
if (current_pos.getDistanceFrom(pos) < radius) {
|
||||||
|
MapNode n = m_map->getNodeNoEx(current_pos);
|
||||||
|
nodes.push_back(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
void ServerEnvironment::addActiveBlockModifier(ActiveBlockModifier *abm)
|
void ServerEnvironment::addActiveBlockModifier(ActiveBlockModifier *abm)
|
||||||
{
|
{
|
||||||
m_abms.push_back(ABMWithState(abm));
|
m_abms.push_back(ABMWithState(abm));
|
||||||
@@ -1875,6 +1890,7 @@ void ClientEnvironment::step(float dtime)
|
|||||||
Get the speed the player is going
|
Get the speed the player is going
|
||||||
*/
|
*/
|
||||||
bool is_climbing = lplayer->is_climbing;
|
bool is_climbing = lplayer->is_climbing;
|
||||||
|
bool linked = lplayer->m_linked;
|
||||||
|
|
||||||
f32 player_speed = lplayer->getSpeed().getLength();
|
f32 player_speed = lplayer->getSpeed().getLength();
|
||||||
|
|
||||||
@@ -1903,96 +1919,98 @@ void ClientEnvironment::step(float dtime)
|
|||||||
/*
|
/*
|
||||||
Stuff that has a maximum time increment
|
Stuff that has a maximum time increment
|
||||||
*/
|
*/
|
||||||
|
//TODO at this position possibly a better solution is required!
|
||||||
|
if (!linked) {
|
||||||
|
u32 loopcount = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
loopcount++;
|
||||||
|
|
||||||
u32 loopcount = 0;
|
f32 dtime_part;
|
||||||
do
|
if(dtime_downcount > dtime_max_increment)
|
||||||
{
|
|
||||||
loopcount++;
|
|
||||||
|
|
||||||
f32 dtime_part;
|
|
||||||
if(dtime_downcount > dtime_max_increment)
|
|
||||||
{
|
|
||||||
dtime_part = dtime_max_increment;
|
|
||||||
dtime_downcount -= dtime_part;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dtime_part = dtime_downcount;
|
|
||||||
/*
|
|
||||||
Setting this to 0 (no -=dtime_part) disables an infinite loop
|
|
||||||
when dtime_part is so small that dtime_downcount -= dtime_part
|
|
||||||
does nothing
|
|
||||||
*/
|
|
||||||
dtime_downcount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Handle local player
|
|
||||||
*/
|
|
||||||
|
|
||||||
{
|
|
||||||
v3f lplayerpos = lplayer->getPosition();
|
|
||||||
|
|
||||||
// Apply physics
|
|
||||||
if(free_move == false && is_climbing == false)
|
|
||||||
{
|
{
|
||||||
// Gravity
|
dtime_part = dtime_max_increment;
|
||||||
v3f speed = lplayer->getSpeed();
|
dtime_downcount -= dtime_part;
|
||||||
if(lplayer->swimming_up == false)
|
}
|
||||||
speed.Y -= 9.81 * BS * dtime_part * 2;
|
else
|
||||||
|
{
|
||||||
// Water resistance
|
dtime_part = dtime_downcount;
|
||||||
if(lplayer->in_water_stable || lplayer->in_water)
|
/*
|
||||||
{
|
Setting this to 0 (no -=dtime_part) disables an infinite loop
|
||||||
f32 max_down = 2.0*BS;
|
when dtime_part is so small that dtime_downcount -= dtime_part
|
||||||
if(speed.Y < -max_down) speed.Y = -max_down;
|
does nothing
|
||||||
|
*/
|
||||||
f32 max = 2.5*BS;
|
dtime_downcount = 0;
|
||||||
if(speed.getLength() > max)
|
|
||||||
{
|
|
||||||
speed = speed / speed.getLength() * max;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lplayer->setSpeed(speed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Move the lplayer.
|
Handle local player
|
||||||
This also does collision detection.
|
|
||||||
*/
|
*/
|
||||||
lplayer->move(dtime_part, *m_map, position_max_increment,
|
|
||||||
&player_collisions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while(dtime_downcount > 0.001);
|
|
||||||
|
|
||||||
//std::cout<<"Looped "<<loopcount<<" times."<<std::endl;
|
|
||||||
|
|
||||||
for(core::list<CollisionInfo>::Iterator
|
|
||||||
i = player_collisions.begin();
|
|
||||||
i != player_collisions.end(); i++)
|
|
||||||
{
|
|
||||||
CollisionInfo &info = *i;
|
|
||||||
if(info.t == COLLISION_FALL)
|
|
||||||
{
|
|
||||||
//f32 tolerance = BS*10; // 2 without damage
|
|
||||||
f32 tolerance = BS*12; // 3 without damage
|
|
||||||
f32 factor = 1;
|
|
||||||
if(info.speed > tolerance)
|
|
||||||
{
|
{
|
||||||
f32 damage_f = (info.speed - tolerance)/BS*factor;
|
v3f lplayerpos = lplayer->getPosition();
|
||||||
u16 damage = (u16)(damage_f+0.5);
|
|
||||||
if(lplayer->hp > damage)
|
|
||||||
lplayer->hp -= damage;
|
|
||||||
else
|
|
||||||
lplayer->hp = 0;
|
|
||||||
|
|
||||||
ClientEnvEvent event;
|
// Apply physics
|
||||||
event.type = CEE_PLAYER_DAMAGE;
|
if(free_move == false && is_climbing == false)
|
||||||
event.player_damage.amount = damage;
|
{
|
||||||
event.player_damage.send_to_server = true;
|
// Gravity
|
||||||
m_client_event_queue.push_back(event);
|
v3f speed = lplayer->getSpeed();
|
||||||
|
if(lplayer->swimming_up == false)
|
||||||
|
speed.Y -= 9.81 * BS * dtime_part * 2;
|
||||||
|
|
||||||
|
// Water resistance
|
||||||
|
if(lplayer->in_water_stable || lplayer->in_water)
|
||||||
|
{
|
||||||
|
f32 max_down = 2.0*BS;
|
||||||
|
if(speed.Y < -max_down) speed.Y = -max_down;
|
||||||
|
|
||||||
|
f32 max = 2.5*BS;
|
||||||
|
if(speed.getLength() > max)
|
||||||
|
{
|
||||||
|
speed = speed / speed.getLength() * max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lplayer->setSpeed(speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Move the lplayer.
|
||||||
|
This also does collision detection.
|
||||||
|
*/
|
||||||
|
lplayer->move(dtime_part, *m_map, position_max_increment,
|
||||||
|
&player_collisions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(dtime_downcount > 0.001);
|
||||||
|
|
||||||
|
//std::cout<<"Looped "<<loopcount<<" times."<<std::endl;
|
||||||
|
|
||||||
|
for(core::list<CollisionInfo>::Iterator
|
||||||
|
i = player_collisions.begin();
|
||||||
|
i != player_collisions.end(); i++)
|
||||||
|
{
|
||||||
|
CollisionInfo &info = *i;
|
||||||
|
if(info.t == COLLISION_FALL)
|
||||||
|
{
|
||||||
|
//f32 tolerance = BS*10; // 2 without damage
|
||||||
|
f32 tolerance = BS*12; // 3 without damage
|
||||||
|
f32 factor = 1;
|
||||||
|
if(info.speed > tolerance)
|
||||||
|
{
|
||||||
|
f32 damage_f = (info.speed - tolerance)/BS*factor;
|
||||||
|
u16 damage = (u16)(damage_f+0.5);
|
||||||
|
if(lplayer->hp > damage)
|
||||||
|
lplayer->hp -= damage;
|
||||||
|
else
|
||||||
|
lplayer->hp = 0;
|
||||||
|
|
||||||
|
ClientEnvEvent event;
|
||||||
|
event.type = CEE_PLAYER_DAMAGE;
|
||||||
|
event.player_damage.amount = damage;
|
||||||
|
event.player_damage.send_to_server = true;
|
||||||
|
m_client_event_queue.push_back(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -270,6 +270,9 @@ class ServerEnvironment : public Environment
|
|||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Find all nodes inside a radius around a point
|
||||||
|
core::list<MapNode> getNodesInsideRadius(v3s16 pos, float radius);
|
||||||
|
|
||||||
// Find all active objects inside a radius around a point
|
// Find all active objects inside a radius around a point
|
||||||
std::set<u16> getObjectsInsideRadius(v3f pos, float radius);
|
std::set<u16> getObjectsInsideRadius(v3f pos, float radius);
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "serverobject.h"
|
#include "serverobject.h"
|
||||||
#include "content_mapnode.h"
|
#include "content_mapnode.h"
|
||||||
#include "content_sao.h"
|
#include "content_sao.h"
|
||||||
|
#include "content_sao_item.h"
|
||||||
#include "environment.h"
|
#include "environment.h"
|
||||||
#include "mapblock.h"
|
#include "mapblock.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
|
|||||||
99
src/mesh.cpp
99
src/mesh.cpp
@@ -82,6 +82,105 @@ scene::IAnimatedMesh* createCubeMesh(v3f scale)
|
|||||||
return anim_mesh;
|
return anim_mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scene::IAnimatedMesh* createCubeMesh(v3f scale,core::aabbox3d<f32> box)
|
||||||
|
{
|
||||||
|
video::SColor c(255,255,255,255);
|
||||||
|
video::S3DVertex vertices[24] =
|
||||||
|
{
|
||||||
|
// Up
|
||||||
|
video::S3DVertex(box.MinEdge.X,box.MaxEdge.Y,box.MinEdge.Z, 0,1,0, c, 0,1),
|
||||||
|
video::S3DVertex(box.MinEdge.X,box.MaxEdge.Y,box.MaxEdge.Z, 0,1,0, c, 0,0),
|
||||||
|
video::S3DVertex(box.MaxEdge.X,box.MaxEdge.Y,box.MaxEdge.Z, 0,1,0, c, 1,0),
|
||||||
|
video::S3DVertex(box.MaxEdge.X,box.MaxEdge.Y,box.MinEdge.Z, 0,1,0, c, 1,1),
|
||||||
|
// Down
|
||||||
|
video::S3DVertex(box.MinEdge.X,box.MinEdge.Y,box.MinEdge.Z, 0,-1,0, c, 0,0),
|
||||||
|
video::S3DVertex(box.MaxEdge.X,box.MinEdge.Y,box.MinEdge.Z, 0,-1,0, c, 1,0),
|
||||||
|
video::S3DVertex(box.MaxEdge.X,box.MinEdge.Y,box.MaxEdge.Z, 0,-1,0, c, 1,1),
|
||||||
|
video::S3DVertex(box.MinEdge.X,box.MinEdge.Y,box.MaxEdge.Z, 0,-1,0, c, 0,1),
|
||||||
|
// Right
|
||||||
|
video::S3DVertex(box.MaxEdge.X,box.MinEdge.Y,box.MinEdge.Z, 1,0,0, c, 0,1),
|
||||||
|
video::S3DVertex(box.MaxEdge.X,box.MaxEdge.Y,box.MinEdge.Z, 1,0,0, c, 0,0),
|
||||||
|
video::S3DVertex(box.MaxEdge.X,box.MaxEdge.Y,box.MaxEdge.Z, 1,0,0, c, 1,0),
|
||||||
|
video::S3DVertex(box.MaxEdge.X,box.MinEdge.Y,box.MaxEdge.Z, 1,0,0, c, 1,1),
|
||||||
|
// Left
|
||||||
|
video::S3DVertex(box.MinEdge.X,box.MinEdge.Y,box.MinEdge.Z, -1,0,0, c, 1,1),
|
||||||
|
video::S3DVertex(box.MinEdge.X,box.MinEdge.Y,box.MaxEdge.Z, -1,0,0, c, 0,1),
|
||||||
|
video::S3DVertex(box.MinEdge.X,box.MaxEdge.Y,box.MaxEdge.Z, -1,0,0, c, 0,0),
|
||||||
|
video::S3DVertex(box.MinEdge.X,box.MaxEdge.Y,box.MinEdge.Z, -1,0,0, c, 1,0),
|
||||||
|
// Back
|
||||||
|
video::S3DVertex(box.MinEdge.X,box.MinEdge.Y,box.MaxEdge.Z, 0,0,1, c, 1,1),
|
||||||
|
video::S3DVertex(box.MaxEdge.X,box.MinEdge.Y,box.MaxEdge.Z, 0,0,1, c, 0,1),
|
||||||
|
video::S3DVertex(box.MaxEdge.X,box.MaxEdge.Y,box.MaxEdge.Z, 0,0,1, c, 0,0),
|
||||||
|
video::S3DVertex(box.MinEdge.X,box.MaxEdge.Y,box.MaxEdge.Z, 0,0,1, c, 1,0),
|
||||||
|
// Front
|
||||||
|
video::S3DVertex(box.MinEdge.X,box.MinEdge.Y,box.MinEdge.Z, 0,0,-1, c, 0,1),
|
||||||
|
video::S3DVertex(box.MinEdge.X,box.MaxEdge.Y,box.MinEdge.Z, 0,0,-1, c, 0,0),
|
||||||
|
video::S3DVertex(box.MaxEdge.X,box.MaxEdge.Y,box.MinEdge.Z, 0,0,-1, c, 1,0),
|
||||||
|
video::S3DVertex(box.MaxEdge.X,box.MinEdge.Y,box.MinEdge.Z, 0,0,-1, c, 1,1),
|
||||||
|
};
|
||||||
|
|
||||||
|
u16 indices[6] = {0,1,2,2,3,0};
|
||||||
|
|
||||||
|
scene::SMesh *mesh = new scene::SMesh();
|
||||||
|
for (u32 i=0; i<6; ++i)
|
||||||
|
{
|
||||||
|
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||||
|
buf->append(vertices + 4 * i, 4, indices, 6);
|
||||||
|
mesh->addMeshBuffer(buf);
|
||||||
|
buf->drop();
|
||||||
|
}
|
||||||
|
scene::SAnimatedMesh *anim_mesh = new scene::SAnimatedMesh(mesh);
|
||||||
|
mesh->drop();
|
||||||
|
scaleMesh(anim_mesh, scale); // also recalculates bounding box
|
||||||
|
return anim_mesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
scene::IAnimatedMesh* createPlantMesh(v3f scale)
|
||||||
|
{
|
||||||
|
video::SColor c(255,255,255,255);
|
||||||
|
video::S3DVertex vertices[16] =
|
||||||
|
{
|
||||||
|
// Plane 1 Front
|
||||||
|
video::S3DVertex(-0.5,-0.5,-0.5, 0.5,0,-0.5, c, 0,1),
|
||||||
|
video::S3DVertex(-0.5,+0.5,-0.5, 0.5,0,-0.5, c, 0,0),
|
||||||
|
video::S3DVertex(+0.5,+0.5,+0.5, 0.5,0,-0.5, c, 1,0),
|
||||||
|
video::S3DVertex(+0.5,-0.5,+0.5, 0.5,0,-0.5, c, 1,1),
|
||||||
|
// Plane 1 Back
|
||||||
|
video::S3DVertex(+0.5,-0.5,+0.5, -0.5,0,0.5, c, 1,1),
|
||||||
|
video::S3DVertex(+0.5,+0.5,+0.5, -0.5,0,0.5, c, 1,0),
|
||||||
|
video::S3DVertex(-0.5,+0.5,-0.5, -0.5,0,0.5, c, 0,0),
|
||||||
|
video::S3DVertex(-0.5,-0.5,-0.5, -0.5,0,0.5, c, 0,1),
|
||||||
|
|
||||||
|
// Plane 2 Front
|
||||||
|
video::S3DVertex(-0.5,-0.5,+0.5, -0.5,0,-0.5, c, 1,1),
|
||||||
|
video::S3DVertex(-0.5,+0.5,+0.5, -0.5,0,-0.5, c, 1,0),
|
||||||
|
video::S3DVertex(+0.5,+0.5,-0.5, -0.5,0,-0.5, c, 0,0),
|
||||||
|
video::S3DVertex(+0.5,-0.5,-0.5, -0.5,0,-0.5, c, 0,1),
|
||||||
|
|
||||||
|
// Plane 2 Back
|
||||||
|
video::S3DVertex(+0.5,-0.5,-0.5, 0.5,0,0.5, c, 0,1),
|
||||||
|
video::S3DVertex(+0.5,+0.5,-0.5, 0.5,0,0.5, c, 0,0),
|
||||||
|
video::S3DVertex(-0.5,+0.5,+0.5, 0.5,0,0.5, c, 1,0),
|
||||||
|
video::S3DVertex(-0.5,-0.5,+0.5, 0.5,0,0.5, c, 1,1)
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
u16 indices[6] = {0,1,2,2,3,0};
|
||||||
|
|
||||||
|
scene::SMesh *mesh = new scene::SMesh();
|
||||||
|
for (u32 i=0; i<4; ++i)
|
||||||
|
{
|
||||||
|
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||||
|
buf->append(vertices + 4 * i, 4, indices, 6);
|
||||||
|
mesh->addMeshBuffer(buf);
|
||||||
|
buf->drop();
|
||||||
|
}
|
||||||
|
scene::SAnimatedMesh *anim_mesh = new scene::SAnimatedMesh(mesh);
|
||||||
|
mesh->drop();
|
||||||
|
scaleMesh(anim_mesh, scale); // also recalculates bounding box
|
||||||
|
return anim_mesh;
|
||||||
|
}
|
||||||
|
|
||||||
static scene::IAnimatedMesh* extrudeARGB(u32 twidth, u32 theight, u8 *data)
|
static scene::IAnimatedMesh* extrudeARGB(u32 twidth, u32 theight, u8 *data)
|
||||||
{
|
{
|
||||||
const s32 argb_wstep = 4 * twidth;
|
const s32 argb_wstep = 4 * twidth;
|
||||||
|
|||||||
19
src/mesh.h
19
src/mesh.h
@@ -31,6 +31,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
*/
|
*/
|
||||||
scene::IAnimatedMesh* createCubeMesh(v3f scale);
|
scene::IAnimatedMesh* createCubeMesh(v3f scale);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create a new cube mesh not linked to mapnode size.
|
||||||
|
Vertices are defined by given box.
|
||||||
|
|
||||||
|
The resulting mesh has 6 materials (up, down, right, left, back, front)
|
||||||
|
which must be defined by the caller.
|
||||||
|
*/
|
||||||
|
scene::IAnimatedMesh* createCubeMesh(v3f scale,core::aabbox3d<f32> box);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Create a new extruded mesh from a texture.
|
Create a new extruded mesh from a texture.
|
||||||
Maximum bounding box is (+-scale.X/2, +-scale.Y/2, +-scale.Z).
|
Maximum bounding box is (+-scale.X/2, +-scale.Y/2, +-scale.Z).
|
||||||
@@ -41,6 +50,16 @@ scene::IAnimatedMesh* createCubeMesh(v3f scale);
|
|||||||
scene::IAnimatedMesh* createExtrudedMesh(video::ITexture *texture,
|
scene::IAnimatedMesh* createExtrudedMesh(video::ITexture *texture,
|
||||||
video::IVideoDriver *driver, v3f scale);
|
video::IVideoDriver *driver, v3f scale);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create a new plant style mesh.
|
||||||
|
Vertices are at (+-scale.X/2, +-scale.Y/2, +-scale.Z/2).
|
||||||
|
|
||||||
|
The resulting mesh has 4 materials (right, left, back, front)
|
||||||
|
which must be defined by the caller.
|
||||||
|
*/
|
||||||
|
scene::IAnimatedMesh* createPlantMesh(v3f scale);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Multiplies each vertex coordinate by the specified scaling factors
|
Multiplies each vertex coordinate by the specified scaling factors
|
||||||
(componentwise vector multiplication).
|
(componentwise vector multiplication).
|
||||||
|
|||||||
@@ -183,7 +183,8 @@ void Player::deSerialize(std::istream &is)
|
|||||||
LocalPlayer::LocalPlayer(IGameDef *gamedef):
|
LocalPlayer::LocalPlayer(IGameDef *gamedef):
|
||||||
Player(gamedef),
|
Player(gamedef),
|
||||||
m_sneak_node(32767,32767,32767),
|
m_sneak_node(32767,32767,32767),
|
||||||
m_sneak_node_exists(false)
|
m_sneak_node_exists(false),
|
||||||
|
m_linked(false)
|
||||||
{
|
{
|
||||||
// Initialize hp to 0, so that no hearts will be shown if server
|
// Initialize hp to 0, so that no hearts will be shown if server
|
||||||
// doesn't support health points
|
// doesn't support health points
|
||||||
|
|||||||
@@ -251,6 +251,13 @@ class LocalPlayer : public Player
|
|||||||
|
|
||||||
PlayerControl control;
|
PlayerControl control;
|
||||||
|
|
||||||
|
|
||||||
|
inline void Link(bool value) {
|
||||||
|
m_linked = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool m_linked;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// This is used for determining the sneaking range
|
// This is used for determining the sneaking range
|
||||||
v3s16 m_sneak_node;
|
v3s16 m_sneak_node;
|
||||||
|
|||||||
@@ -35,7 +35,11 @@ extern "C" {
|
|||||||
#include "script.h"
|
#include "script.h"
|
||||||
//#include "luna.h"
|
//#include "luna.h"
|
||||||
#include "luaentity_common.h"
|
#include "luaentity_common.h"
|
||||||
#include "content_sao.h" // For LuaEntitySAO
|
#include "content_sao.h"
|
||||||
|
#include "content_sao_lua.h" // For LuaEntitySAO
|
||||||
|
#include "content_sao_item.h"
|
||||||
|
#include "content_sao_rat.h"
|
||||||
|
#include "content_sao_firefly.h"
|
||||||
#include "tooldef.h"
|
#include "tooldef.h"
|
||||||
#include "nodedef.h"
|
#include "nodedef.h"
|
||||||
#include "craftdef.h"
|
#include "craftdef.h"
|
||||||
@@ -46,6 +50,7 @@ extern "C" {
|
|||||||
#include "mapblock.h" // For getNodeBlockPos
|
#include "mapblock.h" // For getNodeBlockPos
|
||||||
#include "content_nodemeta.h"
|
#include "content_nodemeta.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
#include "serverlinkableobject.h"
|
||||||
|
|
||||||
static void stackDump(lua_State *L, std::ostream &o)
|
static void stackDump(lua_State *L, std::ostream &o)
|
||||||
{
|
{
|
||||||
@@ -1753,7 +1758,7 @@ class ObjectRef
|
|||||||
get_server(L)->SendMovePlayer(player);
|
get_server(L)->SendMovePlayer(player);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// moveto(self, pos, continuous=false)
|
// moveto(self, pos, continuous=false)
|
||||||
static int l_moveto(lua_State *L)
|
static int l_moveto(lua_State *L)
|
||||||
{
|
{
|
||||||
@@ -2173,6 +2178,62 @@ class ObjectRef
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// link(parent, offset)
|
||||||
|
static int l_link(lua_State *L)
|
||||||
|
{
|
||||||
|
ObjectRef *ref_child = checkobject(L, 1);
|
||||||
|
ObjectRef *ref_parent = checkobject(L, 2);
|
||||||
|
v3f offset = checkFloatPos(L, 3);
|
||||||
|
|
||||||
|
ServerActiveObject *child = getobject(ref_child);
|
||||||
|
ServerActiveObject *parent = getobject(ref_parent);
|
||||||
|
|
||||||
|
if ((child == NULL) || (parent == NULL)) {
|
||||||
|
errorstream << "LUA: link(): invalid parameters" << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ServerLinkableObject* child_lua = dynamic_cast<ServerLinkableObject*>(child);
|
||||||
|
ServerLinkableObject* parent_lua = dynamic_cast<ServerLinkableObject*>(parent);
|
||||||
|
|
||||||
|
if (child_lua == NULL) return 0;
|
||||||
|
if (parent_lua == NULL) return 0;
|
||||||
|
|
||||||
|
if (child_lua->linkEntity(parent,offset)) {
|
||||||
|
lua_pushboolean(L, true);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// unlink()
|
||||||
|
static int l_unlink(lua_State *L)
|
||||||
|
{
|
||||||
|
ObjectRef *ref = checkobject(L, 1);
|
||||||
|
|
||||||
|
ServerActiveObject *obj = getobject(ref);
|
||||||
|
|
||||||
|
if (obj == NULL) {
|
||||||
|
errorstream << "LUA: unlink(): invalid parameters" << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerLinkableObject* tolink = dynamic_cast<ServerLinkableObject*>(obj);
|
||||||
|
|
||||||
|
if (tolink == NULL) return 0;
|
||||||
|
|
||||||
|
if (tolink->unlinkEntity()) {
|
||||||
|
lua_pushboolean(L, true);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ObjectRef(ServerActiveObject *object):
|
ObjectRef(ServerActiveObject *object):
|
||||||
m_object(object)
|
m_object(object)
|
||||||
@@ -2270,6 +2331,8 @@ const luaL_reg ObjectRef::methods[] = {
|
|||||||
method(ObjectRef, get_look_dir),
|
method(ObjectRef, get_look_dir),
|
||||||
method(ObjectRef, get_look_pitch),
|
method(ObjectRef, get_look_pitch),
|
||||||
method(ObjectRef, get_look_yaw),
|
method(ObjectRef, get_look_yaw),
|
||||||
|
method(ObjectRef, link),
|
||||||
|
method(ObjectRef, unlink),
|
||||||
{0,0}
|
{0,0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2543,6 +2606,35 @@ class EnvRef
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EnvRef:get_objects_inside_radius(pos, radius)
|
||||||
|
static int l_get_nodes_inside_radius(lua_State *L)
|
||||||
|
{
|
||||||
|
// Get the table insert function
|
||||||
|
lua_getglobal(L, "table");
|
||||||
|
lua_getfield(L, -1, "insert");
|
||||||
|
int table_insert = lua_gettop(L);
|
||||||
|
// Get environemnt
|
||||||
|
EnvRef *o = checkobject(L, 1);
|
||||||
|
ServerEnvironment *env = o->m_env;
|
||||||
|
if(env == NULL) return 0;
|
||||||
|
// Do it
|
||||||
|
v3s16 pos = read_v3s16(L, 2);
|
||||||
|
float radius = luaL_checknumber(L, 3);// * BS;
|
||||||
|
core::list<MapNode> nodes = env->getNodesInsideRadius(pos, radius);
|
||||||
|
lua_newtable(L);
|
||||||
|
int table = lua_gettop(L);
|
||||||
|
for(core::list<MapNode>::Iterator
|
||||||
|
i = nodes.begin(); i != nodes.end(); i++){
|
||||||
|
// Insert object reference into table
|
||||||
|
lua_pushvalue(L, table_insert);
|
||||||
|
lua_pushvalue(L, table);
|
||||||
|
pushnode(L, *i, env->getGameDef()->ndef());
|
||||||
|
if(lua_pcall(L, 2, 0, 0))
|
||||||
|
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int gc_object(lua_State *L) {
|
static int gc_object(lua_State *L) {
|
||||||
EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1));
|
EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1));
|
||||||
delete o;
|
delete o;
|
||||||
@@ -2620,6 +2712,7 @@ const luaL_reg EnvRef::methods[] = {
|
|||||||
method(EnvRef, get_meta),
|
method(EnvRef, get_meta),
|
||||||
method(EnvRef, get_player_by_name),
|
method(EnvRef, get_player_by_name),
|
||||||
method(EnvRef, get_objects_inside_radius),
|
method(EnvRef, get_objects_inside_radius),
|
||||||
|
method(EnvRef, get_nodes_inside_radius),
|
||||||
{0,0}
|
{0,0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
53
src/serverlinkableobject.cpp
Normal file
53
src/serverlinkableobject.cpp
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
Copyright (C) 2012 sapier sapier at gmx dot net
|
||||||
|
|
||||||
|
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 "serverlinkableobject.h"
|
||||||
|
|
||||||
|
|
||||||
|
ServerLinkableObject::ServerLinkableObject() {
|
||||||
|
this->m_Linked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerLinkableObject::~ServerLinkableObject() {}
|
||||||
|
|
||||||
|
bool ServerLinkableObject::linkEntity(ServerActiveObject* parent,v3f offset) {
|
||||||
|
//check if entity is in correct state
|
||||||
|
if (this->m_Linked == true) {
|
||||||
|
errorstream<<"ServerLinkableObject: link but object already linked!"<<std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this->m_Linked = true;
|
||||||
|
|
||||||
|
errorstream<<"ServerLinkableObject: try to send link message!"<<std::endl;
|
||||||
|
return sendLinkMsg(parent,offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ServerLinkableObject::unlinkEntity() {
|
||||||
|
//check if entity is in correct state
|
||||||
|
if (this->m_Linked == false) {
|
||||||
|
errorstream<<"ServerLinkableObject: unlink but object not linked!"<<std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->m_Linked = false;
|
||||||
|
|
||||||
|
errorstream<<"ServerLinkableObject: try to send unlink message!"<<std::endl;
|
||||||
|
return sendUnlinkMsg();
|
||||||
|
}
|
||||||
49
src/serverlinkableobject.h
Normal file
49
src/serverlinkableobject.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
Copyright (C) 2012 sapier sapier at gmx dot net
|
||||||
|
|
||||||
|
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 SERVERLINKABLEOBJECT_H_
|
||||||
|
#define SERVERLINKABLEOBJECT_H_
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <irrlichttypes.h>
|
||||||
|
#include "serverobject.h"
|
||||||
|
#include "content_object.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
class ServerLinkableObject {
|
||||||
|
public:
|
||||||
|
ServerLinkableObject();
|
||||||
|
~ServerLinkableObject();
|
||||||
|
|
||||||
|
bool linkEntity(ServerActiveObject* parent,v3f offset);
|
||||||
|
bool unlinkEntity();
|
||||||
|
|
||||||
|
virtual bool sendLinkMsg(ServerActiveObject* parent,v3f offset) = 0;
|
||||||
|
virtual bool sendUnlinkMsg() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
inline bool isLinked() { return m_Linked; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_Linked;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* SERVERLINKABLEOBJECT_H_ */
|
||||||
@@ -43,8 +43,8 @@ ServerActiveObject* ServerActiveObject::create(u8 type,
|
|||||||
const std::string &data)
|
const std::string &data)
|
||||||
{
|
{
|
||||||
// Find factory function
|
// Find factory function
|
||||||
core::map<u16, Factory>::Node *n;
|
core::map<u8, Factory>::Node *n;
|
||||||
n = m_types.find(type);
|
n = ServerActiveObject::getTypes().find(type);
|
||||||
if(n == NULL)
|
if(n == NULL)
|
||||||
{
|
{
|
||||||
// If factory is not found, just return.
|
// If factory is not found, just return.
|
||||||
@@ -58,13 +58,13 @@ ServerActiveObject* ServerActiveObject::create(u8 type,
|
|||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerActiveObject::registerType(u16 type, Factory f)
|
void ServerActiveObject::registerType(u8 type, Factory f)
|
||||||
{
|
{
|
||||||
core::map<u16, Factory>::Node *n;
|
core::map<u8, Factory>::Node *n;
|
||||||
n = m_types.find(type);
|
n = ServerActiveObject::getTypes().find(type);
|
||||||
if(n)
|
if(n)
|
||||||
return;
|
return;
|
||||||
m_types.insert(type, f);
|
ServerActiveObject::getTypes().insert(type, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerActiveObject::getWieldDiggingProperties(ToolDiggingProperties *dst)
|
void ServerActiveObject::getWieldDiggingProperties(ToolDiggingProperties *dst)
|
||||||
|
|||||||
@@ -200,14 +200,17 @@ class ServerActiveObject : public ActiveObject
|
|||||||
typedef ServerActiveObject* (*Factory)
|
typedef ServerActiveObject* (*Factory)
|
||||||
(ServerEnvironment *env, v3f pos,
|
(ServerEnvironment *env, v3f pos,
|
||||||
const std::string &data);
|
const std::string &data);
|
||||||
static void registerType(u16 type, Factory f);
|
static void registerType(u8 type, Factory f);
|
||||||
|
|
||||||
ServerEnvironment *m_env;
|
ServerEnvironment *m_env;
|
||||||
v3f m_base_position;
|
v3f m_base_position;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Used for creating objects based on type
|
static core::map<u8, Factory>& getTypes()
|
||||||
static core::map<u16, Factory> m_types;
|
{
|
||||||
|
static core::map<u8, Factory> types;
|
||||||
|
return types;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -101,13 +101,17 @@ void ServerRemotePlayer::step(float dtime, bool send_recommended)
|
|||||||
if(send_recommended == false)
|
if(send_recommended == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if(isLinked())
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
if(m_position_not_sent)
|
if(m_position_not_sent)
|
||||||
{
|
{
|
||||||
m_position_not_sent = false;
|
m_position_not_sent = false;
|
||||||
|
|
||||||
std::ostringstream os(std::ios::binary);
|
std::ostringstream os(std::ios::binary);
|
||||||
// command (0 = update position)
|
// command (0 = update position)
|
||||||
writeU8(os, 0);
|
writeU8(os,AO_Message_type::SetPosition );
|
||||||
// pos
|
// pos
|
||||||
writeV3F1000(os, getPosition());
|
writeV3F1000(os, getPosition());
|
||||||
// yaw
|
// yaw
|
||||||
@@ -173,7 +177,7 @@ void ServerRemotePlayer::punch(ServerActiveObject *puncher,
|
|||||||
{
|
{
|
||||||
std::ostringstream os(std::ios::binary);
|
std::ostringstream os(std::ios::binary);
|
||||||
// command (1 = punched)
|
// command (1 = punched)
|
||||||
writeU8(os, 1);
|
writeU8(os, AO_Message_type::Punched);
|
||||||
// damage
|
// damage
|
||||||
writeS16(os, hitprop.hp);
|
writeS16(os, hitprop.hp);
|
||||||
// create message and add to list
|
// create message and add to list
|
||||||
@@ -323,4 +327,24 @@ s16 ServerRemotePlayer::getHP()
|
|||||||
return hp;
|
return hp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ServerRemotePlayer::sendLinkMsg(ServerActiveObject* parent,v3f offset) {
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
writeU8(os, AO_Message_type::Link);
|
||||||
|
// parameters
|
||||||
|
writeU16(os, parent->getId());
|
||||||
|
writeV3F1000(os, offset);
|
||||||
|
// create message and add to list
|
||||||
|
ActiveObjectMessage aom(getId(), true, os.str());
|
||||||
|
m_messages_out.push_back(aom);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ServerRemotePlayer::sendUnlinkMsg() {
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
writeU8(os, AO_Message_type::UnLink);
|
||||||
|
// create message and add to list
|
||||||
|
ActiveObjectMessage aom(getId(), true, os.str());
|
||||||
|
m_messages_out.push_back(aom);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,13 +22,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "serverobject.h"
|
#include "serverobject.h"
|
||||||
|
#include "serverlinkableobject.h"
|
||||||
#include "content_object.h" // Object type IDs
|
#include "content_object.h" // Object type IDs
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Player on the server
|
Player on the server
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ServerRemotePlayer : public Player, public ServerActiveObject
|
class ServerRemotePlayer : public Player, public ServerActiveObject, public ServerLinkableObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ServerRemotePlayer(ServerEnvironment *env);
|
ServerRemotePlayer(ServerEnvironment *env);
|
||||||
@@ -97,6 +98,9 @@ class ServerRemotePlayer : public Player, public ServerActiveObject
|
|||||||
// Incremented by step(), read and reset by Server
|
// Incremented by step(), read and reset by Server
|
||||||
float m_time_from_last_punch;
|
float m_time_from_last_punch;
|
||||||
|
|
||||||
|
bool sendLinkMsg(ServerActiveObject* parent,v3f offset);
|
||||||
|
bool sendUnlinkMsg();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_position_not_sent;
|
bool m_position_not_sent;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user