add support for tools that throw objects, add bow and arrow

This commit is contained in:
darkrose 2014-11-22 05:51:31 +10:00
parent 0460fa439b
commit bb7cbedc7e
15 changed files with 122 additions and 16 deletions

BIN
data/textures/arrow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 B

BIN
data/textures/tool_bow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

View File

@ -1602,8 +1602,9 @@ void Client::throwItem(v3f dir, u16 item)
writeU16(buf, TOSERVER_THROWITEM);
os.write((char*)buf, 2);
// Write position
v3f pf = player->getEyePosition();
// Write position - this is one node ahead of the player
// to prevent damage occurring to the thrower
v3f pf = player->getEyePosition()+(dir*BS);
v3s32 position(pf.X*100, pf.Y*100, pf.Z*100);
writeV3S32(buf,position);
os.write((char*)buf, 12);

View File

@ -233,7 +233,7 @@ MobCAO::MobCAO():
m_shooting_unset_timer(0),
m_walking(false),
m_walking_unset_timer(0),
m_draw_type(MDT_NOTHING)
m_draw_type(MDT_AUTO)
{
ClientActiveObject::registerType(getType(), create);
}
@ -251,14 +251,19 @@ void MobCAO::addToScene(scene::ISceneManager *smgr)
video::IVideoDriver* driver = smgr->getVideoDriver();
MobFeatures m = content_mob_features(m_content);
if (m.model != "") {
if (m.texture_display == MDT_EXTRUDED) {
ExtrudedSpriteSceneNode *node = new ExtrudedSpriteSceneNode(smgr->getRootSceneNode(),smgr,-1,v3f(0,0,0),v3f(0,0,0),v3f(5,5,5));
node->setVisible(true);
node->setSprite(g_texturesource->getTextureRaw(m.texture));
m_node = (scene::IMeshSceneNode*)node;
m_draw_type = MDT_EXTRUDED;
updateNodePos();
}else if (m.model != "") {
scene::IAnimatedMesh* mesh = createModelMesh(smgr,m.model.c_str(),true);
if (!mesh)
return;
scene::IAnimatedMeshSceneNode* node;
node = smgr->addAnimatedMeshSceneNode(mesh);
scene::IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode(mesh);
if (node) {
int s;
@ -334,6 +339,8 @@ void MobCAO::updateLight(u8 light_at_pos)
setMeshVerticesColor(((scene::IAnimatedMeshSceneNode*)m_node)->getMesh(), color);
}else if (m_draw_type == MDT_SPRITE) {
((scene::IBillboardSceneNode*)m_node)->setColor(color);
}else if (m_draw_type == MDT_EXTRUDED) {
((ExtrudedSpriteSceneNode*)m_node)->updateLight(li);
}
}
}
@ -357,6 +364,8 @@ void MobCAO::updateNodePos()
rot.Y = (90-pos_translator.yaw_show)+content_mob_features(m_content).model_rotation.Y;
}else if (m_draw_type == MDT_SPRITE) {
rot.Y = pos_translator.yaw_show+content_mob_features(m_content).model_rotation.Y;
}else if (m_draw_type == MDT_EXTRUDED) {
rot.Y = (180-pos_translator.yaw_show)+content_mob_features(m_content).model_rotation.Y;
}
m_node->setRotation(rot);
}
@ -488,6 +497,7 @@ void MobCAO::initialize(const std::string &data)
pos_translator.init(m_position);
// content
m_content = readU16(is);
m_draw_type = content_mob_features(m_content).texture_display;
// yaw
m_yaw = readF1000(is);
// speed

View File

@ -1096,4 +1096,15 @@ void content_craftitem_init()
crafting::set1Any2Recipe(CONTENT_CRAFTITEM_LEATHER,CONTENT_CRAFTITEM_DYE_BLACK,CONTENT_CRAFTITEM_LEATHER_BLACK);
lists::add("craftguide",i);
lists::add("creative",i);
i = CONTENT_CRAFTITEM_ARROW;
f = &g_content_craftitem_features[i];
f->content = CONTENT_CRAFTITEM_ARROW;
f->texture = "arrow.png";
f->name = "arrow";
f->description = wgettext("Arrow");
f->shot_item = CONTENT_MOB_ARROW;
crafting::set1over4Recipe(CONTENT_CRAFTITEM_STEEL_INGOT,CONTENT_CRAFTITEM_STICK,CONTENT_CRAFTITEM_ARROW);
lists::add("craftguide",i);
lists::add("creative",i);
}

View File

@ -46,6 +46,8 @@ struct CraftItemFeatures {
content_t drop_item;
// used by snowballs and such... things that are thrown
content_t thrown_item;
// used by arrows and such... things that are shot by a tool
content_t shot_item;
CraftItemFeatures():
content(CONTENT_IGNORE),
@ -57,7 +59,8 @@ struct CraftItemFeatures {
edible(0),
drop_count(-1),
drop_item(CONTENT_IGNORE),
thrown_item(CONTENT_IGNORE)
thrown_item(CONTENT_IGNORE),
shot_item(CONTENT_IGNORE)
{}
};
@ -166,5 +169,6 @@ CraftItemFeatures & content_craftitem_features(std::string subname);
#define CONTENT_CRAFTITEM_LEATHER_RED (CONTENT_CRAFTITEM_MASK | 0x68)
#define CONTENT_CRAFTITEM_LEATHER_YELLOW (CONTENT_CRAFTITEM_MASK | 0x69)
#define CONTENT_CRAFTITEM_LEATHER_BLACK (CONTENT_CRAFTITEM_MASK | 0x6A)
#define CONTENT_CRAFTITEM_ARROW (CONTENT_CRAFTITEM_MASK | 0x6B)
#endif

View File

@ -530,4 +530,21 @@ void content_mob_init()
f->contact_place_node = CONTENT_SNOW;
f->contact_drop_item = CONTENT_CRAFTITEM_SNOW_BALL;
f->setCollisionBox(aabb3f(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.));
i = CONTENT_MOB_ARROW;
f = &g_content_mob_features[i];
f->content = i;
f->level = MOB_AGGRESSIVE;
f->setTexture("arrow.png");
f->texture_display = MDT_EXTRUDED;
f->model_offset = v3f(0,0.2,0);
f->punch_action = MPA_IGNORE;
f->motion = MM_THROWN;
f->motion_type = MMT_FLY;
f->notices_player = true;
f->attack_player_damage = 1;
f->attack_player_range = v3f(1,1,1);
f->lifetime = 20.0;
f->contact_drop_item = CONTENT_CRAFTITEM_ARROW;
f->setCollisionBox(aabb3f(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.));
}

View File

@ -79,11 +79,14 @@ enum MobAnimationKey
enum MobDrawType
{
MDT_NOTHING = 0,
MDT_AUTO,
MDT_MODEL,
MDT_BLOCK,
MDT_SPRITE
MDT_SPRITE,
MDT_EXTRUDED
};
#define CONTENT_MOB_MASK 0x2000
struct MobFeatures {
@ -93,6 +96,7 @@ struct MobFeatures {
TileSpec tiles[6];
#endif
std::string texture;
MobDrawType texture_display;
std::string model;
std::map<MobAnimationKey,int> animations;
v3f model_scale;
@ -219,6 +223,7 @@ struct MobFeatures {
{
content = CONTENT_IGNORE;
texture = "";
texture_display = MDT_AUTO;
model = "";
model_scale = v3f(1.0,1.0,1.0);
model_offset = v3f(0,0,0);
@ -307,5 +312,6 @@ void content_mob_init();
#define CONTENT_MOB_TAMEWOLF (CONTENT_MOB_MASK | 0x0C)
#define CONTENT_MOB_SHEEP (CONTENT_MOB_MASK | 0x0D)
#define CONTENT_MOB_SNOWBALL (CONTENT_MOB_MASK | 0x0E)
#define CONTENT_MOB_ARROW (CONTENT_MOB_MASK | 0x0F)
#endif

View File

@ -1093,6 +1093,8 @@ void MobSAO::stepMotionThrown(float dtime)
m_base_position += m_speed * dtime;
m_speed.Y -= 10.0*BS*dtime;
m_yaw = wrapDegrees_180(180./PI*atan2(m_speed.Z, m_speed.X));
v3s16 pos_i = floatToInt(m_base_position, BS);
if (!checkFreePosition(pos_i)) {
if (m.contact_explosion_diameter > 0)
@ -1118,6 +1120,8 @@ void MobSAO::stepMotionConstant(float dtime)
MobFeatures m = content_mob_features(m_content);
m_base_position += m_speed * dtime;
m_yaw = wrapDegrees_180(180./PI*atan2(m_speed.Z, m_speed.X));
v3s16 pos_i = floatToInt(m_base_position, BS);
if (!checkFreePosition(pos_i)) {
if (m.contact_explosion_diameter > 0)

View File

@ -505,4 +505,23 @@ void content_toolitem_init()
crafting::setSpearRecipe(CONTENT_CRAFTITEM_STEEL_INGOT,CONTENT_TOOLITEM_STEELSPEAR);
lists::add("craftguide",i);
lists::add("creative",i);
i = CONTENT_TOOLITEM_BOW;
f = &g_content_toolitem_features[i];
f->content = i;
f->texture = "tool_bow.png";
f->name = "bow";
f->description = wgettext("Bow");
f->type = TT_SPECIAL;
f->thrown_item = CONTENT_CRAFTITEM_ARROW;
{
content_t r[9] = {
CONTENT_CRAFTITEM_STRING, CONTENT_CRAFTITEM_STICK, CONTENT_IGNORE,
CONTENT_CRAFTITEM_STRING, CONTENT_IGNORE, CONTENT_CRAFTITEM_STICK,
CONTENT_CRAFTITEM_STRING, CONTENT_CRAFTITEM_STICK, CONTENT_IGNORE
};
crafting::setRecipe(r,i,1);
}
lists::add("craftguide",i);
lists::add("creative",i);
}

View File

@ -40,6 +40,8 @@ struct ToolItemFeatures {
f32 hardness;
// the dig time of this tool
f32 dig_time;
// used for eg. bows throwing an arrow
content_t thrown_item;
ToolItemFeatures():
content(CONTENT_IGNORE),
@ -53,7 +55,8 @@ struct ToolItemFeatures {
liquids_pointable(false),
type(TT_NONE),
hardness(0.),
dig_time(3.)
dig_time(3.),
thrown_item(CONTENT_IGNORE)
{}
};
struct DiggingProperties
@ -114,5 +117,6 @@ ToolItemFeatures & content_toolitem_features(std::string subname);
#define CONTENT_TOOLITEM_STONESPEAR (CONTENT_TOOLITEM_MASK | 0x1D)
#define CONTENT_TOOLITEM_FLINTSPEAR (CONTENT_TOOLITEM_MASK | 0x1E)
#define CONTENT_TOOLITEM_STEELSPEAR (CONTENT_TOOLITEM_MASK | 0x1F)
#define CONTENT_TOOLITEM_BOW (CONTENT_TOOLITEM_MASK | 0x20)
#endif

View File

@ -1678,14 +1678,16 @@ void the_game(
bool left_punch_muted = false;
InventoryItem *wield = (InventoryItem*)client.getLocalPlayer()->getWieldItem();
InventoryList *ilist;
if (
wield
&& (
content_craftitem_features(wield->getContent()).thrown_item != CONTENT_IGNORE
//|| (
//content_toolitem_features(wield->getContent()).thrown_item != CONTENT_IGNORE
//&& client.getLocalPlayer()->inventory.find(content_toolitem_features(wield->getContent()).thrown_item) > -1
//)
|| (
content_toolitem_features(wield->getContent()).thrown_item != CONTENT_IGNORE
&& (ilist = client.getLocalPlayer()->inventory.getList("main")) != NULL
&& ilist->findItem(content_toolitem_features(wield->getContent()).thrown_item) != NULL
)
) && input->getLeftClicked()
) {
client.throwItem(camera_direction,g_selected_item);

View File

@ -672,6 +672,19 @@ InventoryItem * InventoryList::takeItem(u32 i, u32 count)
return NULL;
}
InventoryItem * InventoryList::findItem(content_t c, u16 *item_i)
{
for (u32 i=0; i<m_items.size(); i++) {
InventoryItem *item = getItem(i);
if (item && item->getContent() == c) {
if (item_i)
*item_i = i;
return item;
}
}
return NULL;
}
void InventoryList::decrementMaterials(u16 count)
{
for (u32 i=0; i<m_items.size(); i++) {

View File

@ -591,6 +591,9 @@ public:
// Returns NULL if couldn't take any.
InventoryItem * takeItem(u32 i, u32 count);
// find a stack containing an item
InventoryItem *findItem(content_t item, u16 *item_i = NULL);
// Decrements amount of every material item
void decrementMaterials(u16 count);

View File

@ -2125,8 +2125,20 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
content_t thrown = content_craftitem_features(item->getContent()).thrown_item;
// We can throw it, right?
if (thrown == CONTENT_IGNORE)
return;
if (thrown == CONTENT_IGNORE) {
// it may be a tool that throws something else
thrown = content_toolitem_features(item->getContent()).thrown_item;
if (thrown == CONTENT_IGNORE)
return;
u16 i;
item = ilist->findItem(thrown,&i);
if (!item)
return;
// We can throw it, right?
thrown = content_craftitem_features(item->getContent()).shot_item;
if (thrown == CONTENT_IGNORE)
return;
}
if (g_settings->getBool("droppable_inventory") == false || (getPlayerPrivs(player) & PRIV_BUILD) == 0) {
infostream<<"Not allowing player to drop item: creative mode and no build privs"<<std::endl;