switch player states to true percentages, and add hud indicator of last damage, aka "I should make smaller commits"

This commit is contained in:
darkrose 2016-01-18 16:58:21 +10:00
parent 527737a883
commit bdf5345b9d
30 changed files with 546 additions and 442 deletions

BIN
data/textures/body_feet.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 B

BIN
data/textures/body_head.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 B

BIN
data/textures/body_larm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 B

BIN
data/textures/body_lleg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

BIN
data/textures/body_rarm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 B

BIN
data/textures/body_rleg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 B

View File

@ -504,8 +504,10 @@ void Client::step(float dtime)
event.type = CE_PLAYER_SUFFOCATE;
// this will cause the damage screen to flash
// when suffocation starts effecting damage
if (getAir() < 1 && damage > 0)
if (getAir() < 1 && damage > 0) {
event.type = CE_PLAYER_DAMAGE;
player->addDamage(PLAYER_HEAD,DAMAGE_AIR,damage);
}
event.player_damage.amount = damage;
m_client_event_queue.push_back(event);
}
@ -519,8 +521,10 @@ void Client::step(float dtime)
event.type = CE_PLAYER_HUNGER;
// this will cause the damage screen to flash
// when hunger starts effecting damage
if (getHunger() < 1 && damage > 0)
if (getHunger() < 1 && damage > 0) {
event.type = CE_PLAYER_DAMAGE;
player->addDamage(PLAYER_TORSO,DAMAGE_HUNGER,damage);
}
event.player_damage.amount = damage;
m_client_event_queue.push_back(event);
}
@ -1004,7 +1008,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
player->updateAnim(anim_id,pointed);
}
break;
case TOCLIENT_PLAYERHP:
case TOCLIENT_PLAYERSTATE:
{
std::string datastring((char*)&data[2], datasize-2);
std::istringstream is(datastring, std::ios_base::binary);
@ -1013,14 +1017,17 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
u8 hp = readU8(is);
u8 air = readU8(is);
u8 hunger = readU8(is);
player->dirt = readU8(is);
player->wet = readU8(is);
player->blood = readU8(is);
u16 energy_effect = readU16(is);
if (energy_effect > player->energy_effectf)
player->energy_effectf = energy_effect;
player->cold_effectf += readU16(is);
if (m_server_damage) {
if (!player->hp)
if (!player->health)
player->setEnergy(hp);
player->hp = hp;
player->health = hp;
}
if (m_server_suffocation)
player->air = air;
@ -2167,7 +2174,7 @@ u16 Client::getHP()
Player *player = m_env.getLocalPlayer();
if (!player)
return 0;
return player->hp;
return player->health;
}
u16 Client::getAir()

View File

@ -29,7 +29,7 @@
#include "utility.h"
#define PROTOCOL_VERSION 10
#define PROTOCOL_VERSION 11
/* the last protocol version used by 0.3.x minetest-c55 clients */
#define PROTOCOL_DOTTHREE 3
/* this is the oldest protocol that we will allow to connect
@ -89,12 +89,17 @@ enum ToClientCommand
[4] u8 animation_id
*/
TOCLIENT_PLAYERHP = 0x26,
TOCLIENT_PLAYERSTATE = 0x26,
/*
u16 command
s8 hp
s8 air
s8 hunger
u8 dirt
u8 water
u8 blood
u16 energy_effect
u16 cold_effect
*/
TOCLIENT_INVENTORY = 0x27,

View File

@ -433,7 +433,7 @@ void MobCAO::step(float dtime, ClientEnvironment *env)
)
) && fabs(m_position.Z - playerpos.Z) < m.attack_player_range.Z*BS
) {
env->damageLocalPlayerWithArmour(m.attack_player_damage);
env->damageLocalPlayer(PLAYER_TORSO,DAMAGE_ATTACK,m.attack_player_damage);
m_player_hit_timer = 3.0;
}
}

View File

@ -246,8 +246,8 @@ void content_craftitem_init()
f->cook_result = CONTENT_CRAFTITEM_ASH;
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 8;
f->health_effect = 4;
f->hunger_effect = 40;
f->health_effect = 20;
lists::add("creative",i);
lists::add("cooking",i);
@ -269,8 +269,8 @@ void content_craftitem_init()
f->description = wgettext("Apple");
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 6;
f->health_effect = 3;
f->hunger_effect = 30;
f->health_effect = 15;
lists::add("creative",i);
i = CONTENT_CRAFTITEM_APPLE_IRON;
@ -281,8 +281,8 @@ void content_craftitem_init()
f->description = wgettext("Iron Apple");
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 16;
f->health_effect = 8;
f->hunger_effect = 80;
f->health_effect = 40;
{
u16 recipe[9] = {
CONTENT_CRAFTITEM_STEEL_INGOT, CONTENT_IGNORE, CONTENT_CRAFTITEM_STEEL_INGOT,
@ -499,8 +499,8 @@ void content_craftitem_init()
f->description = wgettext("Apple Blossoms");
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 2;
f->health_effect = 1;
f->hunger_effect = 10;
f->health_effect = 5;
f->fuel_time = 30/16;
lists::add("creative",i);
@ -512,8 +512,8 @@ void content_craftitem_init()
f->description = wgettext("Cactus Berry");
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 6;
f->health_effect = 3;
f->hunger_effect = 30;
f->health_effect = 15;
lists::add("creative",i);
i = CONTENT_CRAFTITEM_MUSH;
@ -525,7 +525,7 @@ void content_craftitem_init()
f->description = wgettext("Mush");
f->consumable = true;
f->sound_use = "use-eat";
f->health_effect = -1;
f->health_effect = -5;
lists::add("creative",i);
i = CONTENT_CRAFTITEM_PUMPKINSLICE;
@ -536,8 +536,8 @@ void content_craftitem_init()
f->description = wgettext("Sliced Pumpkin");
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 6;
f->health_effect = 3;
f->hunger_effect = 30;
f->health_effect = 15;
crafting::set1To2Recipe(CONTENT_FARM_PUMPKIN,CONTENT_CRAFTITEM_PUMPKINSLICE);
lists::add("craftguide",i);
lists::add("creative",i);
@ -550,8 +550,8 @@ void content_craftitem_init()
f->description = wgettext("Pumpkin Pie Slice");
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 12;
f->health_effect = 6;
f->hunger_effect = 60;
f->health_effect = 30;
lists::add("craftguide",i);
i = CONTENT_CRAFTITEM_APPLE_PIE_SLICE;
@ -562,8 +562,8 @@ void content_craftitem_init()
f->description = wgettext("Apple Pie Slice");
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 12;
f->health_effect = 6;
f->hunger_effect = 60;
f->health_effect = 30;
lists::add("creative",i);
i = CONTENT_CRAFTITEM_MELONSLICE;
@ -574,8 +574,8 @@ void content_craftitem_init()
f->description = wgettext("Sliced Melon");
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 8;
f->health_effect = 4;
f->hunger_effect = 40;
f->health_effect = 20;
crafting::set1To2Recipe(CONTENT_FARM_MELON,CONTENT_CRAFTITEM_MELONSLICE);
lists::add("craftguide",i);
lists::add("creative",i);
@ -588,8 +588,8 @@ void content_craftitem_init()
f->description = wgettext("Wheat");
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 2;
f->health_effect = 1;
f->hunger_effect = 10;
f->health_effect = 5;
lists::add("creative",i);
i = CONTENT_CRAFTITEM_FLOUR;
@ -600,8 +600,8 @@ void content_craftitem_init()
f->description = wgettext("Flour");
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 2;
f->health_effect = 1;
f->hunger_effect = 10;
f->health_effect = 5;
crafting::set1Any2Recipe(CONTENT_CRAFTITEM_WHEAT,CONTENT_CRAFTITEM_WHEAT,CONTENT_CRAFTITEM_FLOUR);
lists::add("craftguide",i);
lists::add("creative",i);
@ -615,8 +615,8 @@ void content_craftitem_init()
f->cook_result = CONTENT_CRAFTITEM_BREAD;
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 4;
f->health_effect = 2;
f->hunger_effect = 20;
f->health_effect = 10;
crafting::set1Any2Recipe(CONTENT_CRAFTITEM_FLOUR,CONTENT_CRAFTITEM_FLOUR,CONTENT_CRAFTITEM_DOUGH);
lists::add("craftguide",i);
lists::add("creative",i);
@ -630,8 +630,8 @@ void content_craftitem_init()
f->description = wgettext("Bread");
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 10;
f->health_effect = 5;
f->hunger_effect = 50;
f->health_effect = 20;
lists::add("creative",i);
i = CONTENT_CRAFTITEM_POTATO;
@ -643,8 +643,8 @@ void content_craftitem_init()
f->cook_result = CONTENT_CRAFTITEM_ROASTPOTATO;
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 6;
f->health_effect = 3;
f->hunger_effect = 30;
f->health_effect = 15;
lists::add("creative",i);
lists::add("cooking",i);
@ -666,8 +666,8 @@ void content_craftitem_init()
f->description = wgettext("Roast Potato");
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 12;
f->health_effect = 6;
f->hunger_effect = 60;
f->health_effect = 30;
lists::add("creative",i);
i = CONTENT_CRAFTITEM_CARROT;
@ -678,8 +678,8 @@ void content_craftitem_init()
f->description = wgettext("Carrot");
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 6;
f->health_effect = 4;
f->hunger_effect = 30;
f->health_effect = 20;
lists::add("creative",i);
i = CONTENT_CRAFTITEM_CARROT_CAKE_RAW;
@ -691,8 +691,8 @@ void content_craftitem_init()
f->cook_result = CONTENT_CRAFTITEM_CARROT_CAKE;
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 6;
f->health_effect = 3;
f->hunger_effect = 30;
f->health_effect = 20;
crafting::set1over1Recipe(CONTENT_CRAFTITEM_CARROT,CONTENT_CRAFTITEM_DOUGH,CONTENT_CRAFTITEM_CARROT_CAKE_RAW);
lists::add("craftguide",i);
lists::add("cooking",i);
@ -705,8 +705,8 @@ void content_craftitem_init()
f->description = wgettext("Carrot Cake");
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 12;
f->health_effect = 6;
f->hunger_effect = 60;
f->health_effect = 30;
lists::add("creative",i);
i = CONTENT_CRAFTITEM_BEETROOT;
@ -717,8 +717,8 @@ void content_craftitem_init()
f->description = wgettext("Beetroot");
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 6;
f->health_effect = 3;
f->hunger_effect = 30;
f->health_effect = 15;
lists::add("creative",i);
i = CONTENT_CRAFTITEM_GRAPE;
@ -729,8 +729,8 @@ void content_craftitem_init()
f->description = wgettext("Bunch of Grapes");
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 6;
f->health_effect = 4;
f->hunger_effect = 30;
f->health_effect = 20;
lists::add("creative",i);
i = CONTENT_CRAFTITEM_STRING;
@ -786,8 +786,8 @@ void content_craftitem_init()
f->drop_item = CONTENT_MOB_FISH;
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 1;
f->health_effect = -1;
f->hunger_effect = 5;
f->health_effect = -5;
lists::add("creative",i);
lists::add("cooking",i);
@ -800,8 +800,8 @@ void content_craftitem_init()
f->cook_result = CONTENT_CRAFTITEM_ASH;
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 8;
f->health_effect = 6;
f->hunger_effect = 40;
f->health_effect = 30;
lists::add("creative",i);
lists::add("cooking",i);
@ -814,8 +814,8 @@ void content_craftitem_init()
f->cook_result = CONTENT_CRAFTITEM_COOKED_MEAT;
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 1;
f->health_effect = -1;
f->hunger_effect = 5;
f->health_effect = -5;
lists::add("creative",i);
lists::add("cooking",i);
@ -828,8 +828,8 @@ void content_craftitem_init()
f->cook_result = CONTENT_CRAFTITEM_ASH;
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 10;
f->health_effect = 6;
f->hunger_effect = 50;
f->health_effect = 30;
lists::add("creative",i);
lists::add("cooking",i);
@ -1348,8 +1348,8 @@ void content_craftitem_init()
f->drop_count = 1;
f->consumable = true;
f->sound_use = "use-drink";
f->hunger_effect = 3;
f->health_effect = 3;
f->hunger_effect = 15;
f->health_effect = 15;
f->energy_effect = 30;
f->onuse_replace_item = CONTENT_CRAFTITEM_GLASS_BOTTLE;
crafting::set1over1Recipe(CONTENT_CRAFTITEM_GRAPE,CONTENT_CRAFTITEM_GLASS_BOTTLE,CONTENT_CRAFTITEM_GRAPE_JUICE);
@ -1366,8 +1366,8 @@ void content_craftitem_init()
f->drop_count = 1;
f->consumable = true;
f->sound_use = "use-drink";
f->hunger_effect = 2;
f->health_effect = 3;
f->hunger_effect = 10;
f->health_effect = 15;
f->energy_effect = 10;
f->onuse_replace_item = CONTENT_CRAFTITEM_GLASS_BOTTLE;
crafting::set1over1Recipe(CONTENT_CRAFTITEM_APPLE,CONTENT_CRAFTITEM_GLASS_BOTTLE,CONTENT_CRAFTITEM_APPLE_JUICE);
@ -1383,8 +1383,8 @@ void content_craftitem_init()
f->drop_count = 1;
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 1;
f->health_effect = 2;
f->hunger_effect = 5;
f->health_effect = 10;
lists::add("creative",i);
i = CONTENT_CRAFTITEM_TEA;
@ -1397,8 +1397,8 @@ void content_craftitem_init()
f->drop_count = 1;
f->consumable = true;
f->sound_use = "use-drink";
f->hunger_effect = 3;
f->health_effect = 4;
f->hunger_effect = 15;
f->health_effect = 20;
f->cold_effect = 300;
f->energy_effect = 10;
f->onuse_replace_item = CONTENT_CRAFTITEM_STEEL_BOTTLE;
@ -1415,8 +1415,8 @@ void content_craftitem_init()
f->drop_count = 1;
f->consumable = true;
f->sound_use = "use-eat";
f->hunger_effect = 2;
f->health_effect = 3;
f->hunger_effect = 10;
f->health_effect = 15;
f->energy_effect = 30;
lists::add("creative",i);
@ -1430,8 +1430,8 @@ void content_craftitem_init()
f->drop_count = 1;
f->consumable = true;
f->sound_use = "use-drink";
f->hunger_effect = 2;
f->health_effect = 3;
f->hunger_effect = 10;
f->health_effect = 15;
f->cold_effect = 10;
f->energy_effect = 300;
f->onuse_replace_item = CONTENT_CRAFTITEM_STEEL_BOTTLE;
@ -1467,8 +1467,8 @@ void content_craftitem_init()
f->drop_count = 1;
f->consumable = true;
f->sound_use = "use-drink";
f->hunger_effect = 1;
f->health_effect = 1;
f->hunger_effect = 5;
f->health_effect = 5;
f->onuse_replace_item = CONTENT_CRAFTITEM_GLASS_BOTTLE;
lists::add("creative",i);
@ -1482,8 +1482,8 @@ void content_craftitem_init()
f->drop_count = 1;
f->consumable = true;
f->sound_use = "use-drink";
f->hunger_effect = 1;
f->health_effect = 1;
f->hunger_effect = 5;
f->health_effect = 8;
f->cold_effect = 5;
f->onuse_replace_item = CONTENT_CRAFTITEM_STEEL_BOTTLE;
lists::add("creative",i);

View File

@ -1518,7 +1518,6 @@ void meshgen_dirtlike(MeshMakeData *data, v3s16 p, MapNode &n, SelectedNode &sel
}
}
if (faces[1]) {
TileSpec tile = getNodeTile(n,p,v3s16(0,-1,0),selected,NULL);
video::S3DVertex v[4] = {
video::S3DVertex( 0.5*data->m_BS,-0.5*data->m_BS, 0.5*data->m_BS, 0,0,0, video::SColor(255,255,255,255), basetile.texture.x0(), basetile.texture.y0()),
video::S3DVertex(-0.5*data->m_BS,-0.5*data->m_BS, 0.5*data->m_BS, 0,0,0, video::SColor(255,255,255,255), basetile.texture.x1(), basetile.texture.y0()),
@ -2188,7 +2187,7 @@ void meshgen_plantlike_fern(MeshMakeData *data, v3s16 p, MapNode &n, SelectedNod
ContentFeatures *f = &content_features(n);
TileSpec tile = getNodeTile(n,p,v3s16(0,-1,0),selected);
v3f offset(0,0,0);
s16 rot = 0;
int rot = 0;
bool is_dropped = false;
if (data->m_vmanip.getNodeRO(data->m_blockpos_nodes + p + v3s16(0,-1,0)).getContent() == CONTENT_FLOWER_POT) {
offset = v3f(0,-0.25*data->m_BS,0);
@ -2253,7 +2252,7 @@ void meshgen_plantlike_fern(MeshMakeData *data, v3s16 p, MapNode &n, SelectedNod
video::S3DVertex(-0.5*data->m_BS, 0.28125*data->m_BS,1.5*data->m_BS, 0,0,0, video::SColor(255,255,255,255), 0.,0.),
video::S3DVertex( 0.5*data->m_BS, 0.28125*data->m_BS,1.5*data->m_BS, 0,0,0, video::SColor(255,255,255,255), 1.,0.)
};
s16 angle[8] = {
int angle[8] = {
45+rot,
-45+rot,
135+rot,

View File

@ -297,7 +297,7 @@ void content_mapnode_init(bool repeat)
f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
f->type = CMT_STONE;
f->hardness = 1.0;
f->warmth_per_second = 2;
f->warmth_per_second = 10;
lists::add("creative",i);
i = CONTENT_COAL;
@ -1695,7 +1695,7 @@ void content_mapnode_init(bool repeat)
f->dug_item = std::string("CraftItem snow_ball 9");
f->type = CMT_DIRT;
f->hardness = 0.3;
f->warmth_per_second = 2;
f->warmth_per_second = 10;
crafting::setHardBlockRecipe(CONTENT_CRAFTITEM_SNOW_BALL,CONTENT_SNOW_BLOCK);
lists::add("craftguide",i);
lists::add("creative",i);
@ -1784,7 +1784,7 @@ void content_mapnode_init(bool repeat)
f->hardness = 0.3;
f->pressure_type = CST_CRUSHABLE;
f->suffocation_per_second = 0;
f->warmth_per_second = 2;
f->warmth_per_second = 10;
lists::add("creative",i);
lists::add("decrafting",i);
@ -2159,8 +2159,8 @@ void content_mapnode_init(bool repeat)
f->buildable_to = true;
f->air_equivalent = true;
f->pressure_type = CST_CRUSHED;
f->suffocation_per_second = 15;
f->pressure_per_second = 10;
f->suffocation_per_second = 75;
f->pressure_per_second = 50;
i = CONTENT_WATER;
f = &content_features(i);
@ -2190,7 +2190,7 @@ void content_mapnode_init(bool repeat)
f->post_effect_color = video::SColor(64, 100, 100, 200);
#endif
f->sound_ambient = "env-water";
f->suffocation_per_second = 2;
f->suffocation_per_second = 10;
i = CONTENT_WATERSOURCE;
f = &content_features(i);
@ -2220,7 +2220,7 @@ void content_mapnode_init(bool repeat)
f->type = CMT_LIQUID;
f->hardness = 0.5;
f->pressure_type = CST_CRUSHABLE;
f->suffocation_per_second = 2;
f->suffocation_per_second = 10;
i = CONTENT_LAVA;
f = &content_features(i);
@ -2245,7 +2245,7 @@ void content_mapnode_init(bool repeat)
f->liquid_alternative_flowing = CONTENT_LAVA;
f->liquid_alternative_source = CONTENT_LAVASOURCE;
f->liquid_viscosity = LAVA_VISC;
f->damage_per_second = 4*2;
f->damage_per_second = 40;
#ifndef SERVER
f->post_effect_color = video::SColor(192, 255, 64, 0);
#endif
@ -2272,7 +2272,7 @@ void content_mapnode_init(bool repeat)
f->liquid_alternative_flowing = CONTENT_LAVA;
f->liquid_alternative_source = CONTENT_LAVASOURCE;
f->liquid_viscosity = LAVA_VISC;
f->damage_per_second = 4*2;
f->damage_per_second = 40;
f->sound_ambient = "env-lava";
#ifndef SERVER
f->post_effect_color = video::SColor(192, 255, 64, 0);

View File

@ -752,7 +752,7 @@ void content_mapnode_plants(bool repeat)
f->param_type = CPT_LIGHT;
f->light_propagates = true;
f->sunlight_propagates = true;
f->damage_per_second = 2;
f->damage_per_second = 10;
f->solidness = 0; // drawn separately, makes no faces
f->flammable = 1; // can be replaced by fire if the node under it is set on fire
f->fuel_time = 30/4;

View File

@ -1042,7 +1042,7 @@ void content_mapnode_special(bool repeat)
f->pointable = false;
f->diggable = false;
f->buildable_to = true;
f->damage_per_second = 8;
f->damage_per_second = 40;
f->sound_ambient = "env-fire";
#ifndef SERVER
f->post_effect_color = video::SColor(192, 255, 64, 0);
@ -1063,7 +1063,7 @@ void content_mapnode_special(bool repeat)
f->pointable = false;
f->diggable = false;
f->buildable_to = true;
f->damage_per_second = 8;
f->damage_per_second = 40;
#ifndef SERVER
f->post_effect_color = video::SColor(192, 255, 64, 0);
#endif
@ -1757,7 +1757,7 @@ void content_mapnode_special(bool repeat)
f->pointable = false;
f->diggable = false;
f->buildable_to = true;
f->damage_per_second = 50;
f->damage_per_second = 80;
f->pressure_type = CST_CRUSHED;
#ifndef SERVER
f->setAllTextureTypes(MATERIAL_ALPHA_BLEND);
@ -1777,7 +1777,7 @@ void content_mapnode_special(bool repeat)
f->pointable = false;
f->diggable = false;
f->buildable_to = true;
f->warmth_per_second = 4;
f->damage_per_second = 20;
f->pressure_type = CST_CRUSHED;
#ifndef SERVER
f->setAllTextureTypes(MATERIAL_ALPHA_BLEND);

View File

@ -273,7 +273,6 @@ void mob_spawn_passive(v3s16 pos, bool water, ServerEnvironment *env)
void mob_spawn_hostile(v3s16 pos, bool water, ServerEnvironment *env)
{
std::vector<content_t> can;
int rand = myrand();
u8 level = mobLevelI(g_settings->get("max_mob_level"));
if (level < MOB_AGGRESSIVE)
return;
@ -416,7 +415,7 @@ void content_mob_init()
f->spawn_max_height = 2;
f->sound_spawn = "mob-oerkki-spawn";
f->notices_player = true;
f->attack_player_damage = 3;
f->attack_player_damage = 15;
f->attack_player_range = v3f(1,1,1);
f->lifetime = one_day;
f->setCollisionBox(aabb3f(-BS/3.,0.0,-BS/3., BS/3.,BS*2.,BS/3.));
@ -457,7 +456,7 @@ void content_mob_init()
f->glow_light = LIGHT_MAX-1;
f->notices_player = true;
f->moves_silently = true;
f->attack_player_damage = 3;
f->attack_player_damage = 15;
f->attack_player_range = v3f(2,2,2);
f->contact_explosion_diameter = 3;
f->spawn_naturally = false;
@ -514,7 +513,7 @@ void content_mob_init()
f->spawn_max_height = 40;
f->spawn_chance = 2;
f->notices_player = true;
f->attack_player_damage = 3;
f->attack_player_damage = 15;
f->attack_player_range = v3f(1,1,1);
f->lifetime = one_week;
f->setCollisionBox(aabb3f(-0.7*BS, 0., -0.7*BS, 0.7*BS, 1.5*BS, 0.7*BS));
@ -591,7 +590,7 @@ void content_mob_init()
f->moves_silently = true;
f->spawn_water = true;
f->notices_player = true;
f->attack_player_damage = 3;
f->attack_player_damage = 15;
f->attack_player_range = v3f(1,1,1);
f->lifetime = one_week;
f->setCollisionBox(aabb3f(-0.75*BS, 0., -0.75*BS, 0.75*BS, 1.*BS, 0.75*BS));
@ -621,7 +620,7 @@ void content_mob_init()
f->sound_punch = "mob-wolf-hit";
f->sound_spawn = "mob-wolf-spawn";
f->notices_player = true;
f->attack_player_damage = 3;
f->attack_player_damage = 15;
f->attack_player_range = v3f(1,1,1);
f->lifetime = one_day;
f->setCollisionBox(aabb3f(-0.5*BS, 0., -0.5*BS, 0.5*BS, 1.*BS, 0.5*BS));
@ -772,6 +771,9 @@ void content_mob_init()
f->sound_random = "mob-kitty-env";
f->spawn_min_height = -5;
f->spawn_max_height = 40;
f->notices_player = true;
f->attack_player_damage = 1;
f->attack_player_range = v3f(1,1,1);
f->lifetime = one_week;
f->setCollisionBox(aabb3f(-0.6*BS, 0., -0.6*BS, 0.6*BS, 1.25*BS, 0.6*BS));
lists::add("creative",CONTENT_TOOLITEM_MOB_SPAWNER,1,i);
@ -798,6 +800,9 @@ void content_mob_init()
f->sound_random = "mob-kitty-env";
f->spawn_min_height = -5;
f->spawn_max_height = 40;
f->notices_player = true;
f->attack_player_damage = 1;
f->attack_player_range = v3f(1,1,1);
f->lifetime = one_week;
f->setCollisionBox(aabb3f(-0.6*BS, 0., -0.6*BS, 0.6*BS, 1.25*BS, 0.6*BS));
lists::add("creative",CONTENT_TOOLITEM_MOB_SPAWNER,1,i);
@ -824,6 +829,9 @@ void content_mob_init()
f->sound_random = "mob-kitty-env";
f->spawn_min_height = -5;
f->spawn_max_height = 40;
f->notices_player = true;
f->attack_player_damage = 1;
f->attack_player_range = v3f(1,1,1);
f->lifetime = one_week;
f->setCollisionBox(aabb3f(-0.6*BS, 0., -0.6*BS, 0.6*BS, 1.25*BS, 0.6*BS));
lists::add("creative",CONTENT_TOOLITEM_MOB_SPAWNER,1,i);
@ -850,6 +858,9 @@ void content_mob_init()
f->sound_random = "mob-kitty-env";
f->spawn_min_height = -5;
f->spawn_max_height = 40;
f->notices_player = true;
f->attack_player_damage = 1;
f->attack_player_range = v3f(1,1,1);
f->lifetime = one_week;
f->setCollisionBox(aabb3f(-0.6*BS, 0., -0.6*BS, 0.6*BS, 1.25*BS, 0.6*BS));
lists::add("creative",CONTENT_TOOLITEM_MOB_SPAWNER,1,i);

View File

@ -603,7 +603,6 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
MapNode n = block->getNodeNoEx(p0);
MapNode n1 = block->getNodeNoEx(p0+v3s16(0,1,0));
MapNode n2 = block->getNodeNoEx(p0+v3s16(0,2,0));
u8 light = n1.getLightBlend(getDayNightRatio());
if (n1.getContent() == CONTENT_IGNORE || n2.getContent() == CONTENT_IGNORE)
continue;
if (n.getContent() == CONTENT_WATERSOURCE && n1.getContent() == CONTENT_WATERSOURCE && n2.getContent() == CONTENT_WATERSOURCE) {
@ -1114,7 +1113,6 @@ void ServerEnvironment::step(float dtime)
}
if (block->last_spawn < m_time_of_day-6000) {
MapNode n = block->getNodeNoEx(block->spawn_area);
MapNode n1 = block->getNodeNoEx(block->spawn_area+v3s16(0,1,0));
MapNode n2 = block->getNodeNoEx(block->spawn_area+v3s16(0,2,0));
u8 light = n1.getLightBlend(getDayNightRatio());
@ -2747,10 +2745,12 @@ void ServerEnvironment::step(float dtime)
!searchNearInv(p,v3s16(0,1,0),v3s16(0,16,0),search,NULL)
&& !searchNear(p,v3s16(3,3,3),CONTENT_FIRE,NULL)
) {
n.param1 &= ~0x0F;
n.param1 |= 0x04;
n.envticks = 0;
m_map->addNodeWithEvent(p,n);
MapNode nn(CONTENT_SNOW);
m_map->addNodeWithEvent(p+v3s16(0,1,0),nn);
//n.param1 &= ~0x0F;
//n.param1 |= 0x04;
//n.envticks = 0;
//m_map->addNodeWithEvent(p,n);
}
}
}
@ -3782,17 +3782,13 @@ void ClientEnvironment::step(float dtime)
if (info.t == COLLISION_FALL) {
//f32 tolerance = BS*10; // 2 without damage
f32 tolerance = BS*12; // 3 without damage
f32 factor = 1;
f32 factor = 5;
if (info.speed > BS*4)
m_client->playStepSound(0);
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;
}
lplayer->addDamage(PLAYER_FEET|PLAYER_LLEG|PLAYER_RLEG,DAMAGE_FALL,damage);
ClientEnvEvent event;
event.type = CEE_PLAYER_DAMAGE;
@ -3805,59 +3801,87 @@ void ClientEnvironment::step(float dtime)
/* player damage */
if (m_damage_interval.step(dtime, 1.0)) {
v3f pf = lplayer->getPosition();
v3s16 pp = floatToInt(pf, BS);
// Feet, middle and head
v3s16 p0 = floatToInt(pf - v3f(0, BS*0.1, 0), BS);
MapNode feet = m_map->getNodeNoEx(p0);
v3s16 p1 = floatToInt(pf + v3f(0, BS*0.1, 0), BS);
MapNode legs = m_map->getNodeNoEx(p1);
v3s16 p2 = floatToInt(pf + v3f(0, BS*0.8, 0), BS);
MapNode torso = m_map->getNodeNoEx(p2);
v3s16 p3 = floatToInt(pf + v3f(0, BS*1.6, 0), BS);
MapNode head = m_map->getNodeNoEx(p3);
u32 damage_per_second = 0;
u32 suffocation_per_second = 0;
u32 warmth_per_second = 0;
u32 pressure_per_second = 0;
damage_per_second = content_features(feet).damage_per_second;
damage_per_second = MYMAX(damage_per_second, content_features(legs).damage_per_second);
damage_per_second = MYMAX(damage_per_second, content_features(torso).damage_per_second);
damage_per_second = MYMAX(damage_per_second, content_features(head).damage_per_second);
suffocation_per_second = content_features(head).suffocation_per_second;
warmth_per_second = content_features(feet).warmth_per_second;
warmth_per_second = MYMAX(warmth_per_second, content_features(legs).warmth_per_second);
warmth_per_second = MYMAX(warmth_per_second, content_features(torso).warmth_per_second);
warmth_per_second = MYMAX(warmth_per_second, content_features(head).warmth_per_second);
pressure_per_second = content_features(feet).pressure_per_second;
pressure_per_second = MYMAX(pressure_per_second, content_features(legs).pressure_per_second);
pressure_per_second = MYMAX(pressure_per_second, content_features(torso).pressure_per_second);
pressure_per_second = MYMAX(pressure_per_second, content_features(head).pressure_per_second);
// cold zone
if (warmth_per_second == 0 && pp.Y > 60 && myrand()%10 == 0) {
if (pp.Y < 1024) {
std::vector<content_t> search;
search.push_back(CONTENT_FIRE);
if (!searchNear(pp,v3s16(-4,-2,-4),v3s16(5,5,5),search,NULL))
warmth_per_second = 1;
s16 coldzone = 60;
bool possible_cold = (pp.Y > coldzone && pp.Y < 1024);
v3f ps[6] = {
v3f(0, BS*-0.1, 0),
v3f(0, BS*0.1, 0),
v3f(0, BS*0.8, 0),
v3f(BS*0.4, BS*0.8, 0),
v3f(BS*-0.4, BS*0.8, 0),
v3f(0, BS*1.6, 0)
};
u8 area[6] = {
PLAYER_FEET,
(PLAYER_LLEG|PLAYER_RLEG),
PLAYER_TORSO,
PLAYER_RARM,
PLAYER_LARM,
PLAYER_HEAD
};
ps[3].rotateXZBy(lplayer->getYaw());
ps[4].rotateXZBy(lplayer->getYaw());
pf.Y += BS;
for (int i=0; i<6; i++) {
v3s16 p = floatToInt(pf+ps[i],BS);
MapNode n = m_map->getNodeNoEx(p);
u32 damage = content_features(n).damage_per_second;
u32 suffocation = content_features(n).suffocation_per_second;
u32 warmth = content_features(n).warmth_per_second;
u32 pressure = content_features(n).pressure_per_second;
if (damage > 0) {
u8 t = DAMAGE_UNKNOWN;
switch (n.getContent()) {
case CONTENT_LAVA:
case CONTENT_LAVASOURCE:
t = DAMAGE_LAVA;
break;
case CONTENT_CACTUS:
t = DAMAGE_CACTUS;
break;
case CONTENT_FIRE:
case CONTENT_FIRE_SHORTTERM:
t = DAMAGE_FIRE;
break;
case CONTENT_TNT:
case CONTENT_FLASH:
t = DAMAGE_TNT;
break;
case CONTENT_STEAM:
t = DAMAGE_STEAM;
break;
default:;
}
damageLocalPlayer(area[i],t,damage);
}
if (warmth > 0)
damageLocalPlayer(area[i],DAMAGE_COLD,warmth);
if (pressure > 0)
damageLocalPlayer(area[i],DAMAGE_SPACE,pressure);
if (i < 5)
continue;
if (suffocation > 0) {
damageLocalPlayer(area[i],DAMAGE_AIR,suffocation);
}else if (lplayer->air < 100) {
ClientEnvEvent event;
event.type = CEE_PLAYER_SUFFOCATE;
event.player_damage.amount = -100;
m_client_event_queue.push_back(event);
}
}
if (damage_per_second != 0)
damageLocalPlayer(damage_per_second);
if (suffocation_per_second != 0) {
damageLocalPlayerWithSuffocation(suffocation_per_second);
}else if (lplayer->air < 20) {
ClientEnvEvent event;
event.type = CEE_PLAYER_SUFFOCATE;
event.player_damage.amount = -20;
m_client_event_queue.push_back(event);
// cold zone
if (possible_cold) {
std::vector<content_t> search;
search.push_back(CONTENT_FIRE);
if (!searchNear(pp,v3s16(-4,-2,-4),v3s16(5,5,5),search,NULL))
damageLocalPlayer(PLAYER_ALL,DAMAGE_COLD,5);
}
if (pressure_per_second != 0)
damageLocalPlayerWithVacuum(pressure_per_second);
if (warmth_per_second != 0)
damageLocalPlayerWithWarmth(warmth_per_second);
}
if (m_hunger_interval.step(dtime,5.0)) {
@ -3876,7 +3900,7 @@ void ClientEnvironment::step(float dtime)
if (hungry) {
ClientEnvEvent event;
event.type = CEE_PLAYER_HUNGER;
event.player_damage.amount = hungry;
event.player_damage.amount = 3;
m_client_event_queue.push_back(event);
}
// a little discouragement for running around naked
@ -3897,7 +3921,7 @@ void ClientEnvironment::step(float dtime)
safe = true;
}
if (!safe)
damageLocalPlayer(1);
damageLocalPlayer((PLAYER_TORSO|PLAYER_RLEG|PLAYER_LLEG),DAMAGE_EXPOSURE,2);
}
}
@ -4100,152 +4124,20 @@ void ClientEnvironment::processActiveObjectMessage(u16 id,
Callbacks for activeobjects
*/
void ClientEnvironment::damageLocalPlayer(u8 damage)
void ClientEnvironment::damageLocalPlayer(u8 area, u8 type, u8 damage)
{
if (!m_client->getServerDamage())
return;
LocalPlayer *lplayer = getLocalPlayer();
assert(lplayer);
if (lplayer->hp > damage) {
lplayer->hp -= damage;
}else{
lplayer->hp = 0;
}
ClientEnvEvent event;
event.type = CEE_PLAYER_DAMAGE;
event.player_damage.amount = damage;
m_client_event_queue.push_back(event);
}
void ClientEnvironment::damageLocalPlayerWithArmour(u8 damage)
{
if (!m_client->getServerDamage())
return;
LocalPlayer *lplayer = getLocalPlayer();
assert(lplayer);
f32 effect = lplayer->getArmourProtection();
f32 effect = lplayer->getProtection(area,type);
f32 f_damage = damage;
if (damage > 0 && effect > 0.0) {
f_damage -= f_damage*effect;
ClientEnvEvent event;
event.type = CEE_PLAYER_WEARCLOTHES;
event.player_wear.amount = damage*(500*(2.0-effect));
m_client_event_queue.push_back(event);
if (f_damage < 1.0 && f_damage > 0.0) {
damage = 1.0/f_damage;
if (myrand_range(0,damage) == 0)
f_damage = 1.0;
}
damage = f_damage;
if (damage < 1)
return;
}
if (lplayer->hp > damage) {
lplayer->hp -= damage;
}else{
lplayer->hp = 0;
}
ClientEnvEvent event;
event.type = CEE_PLAYER_DAMAGE;
event.player_damage.amount = damage;
m_client_event_queue.push_back(event);
}
void ClientEnvironment::damageLocalPlayerWithWarmth(u8 damage)
{
if (!m_client->getServerDamage())
return;
LocalPlayer *lplayer = getLocalPlayer();
assert(lplayer);
f32 effect = lplayer->getWarmthProtection();
f32 f_damage = damage;
if (lplayer->cold_effectf > 0.0)
return;
if (damage > 0 && effect > 0.0) {
f_damage -= f_damage*effect;
ClientEnvEvent event;
event.type = CEE_PLAYER_WEARCLOTHES;
event.player_wear.amount = damage*(500*(2.0-effect));
m_client_event_queue.push_back(event);
if (f_damage < 1.0 && f_damage > 0.0) {
damage = 1.0/f_damage;
if (myrand_range(0,damage) == 0)
f_damage = 1.0;
}
damage = f_damage;
if (damage < 1)
return;
}
if (lplayer->hp > damage) {
lplayer->hp -= damage;
}else{
lplayer->hp = 0;
}
ClientEnvEvent event;
event.type = CEE_PLAYER_DAMAGE;
event.player_damage.amount = damage;
m_client_event_queue.push_back(event);
}
void ClientEnvironment::damageLocalPlayerWithVacuum(u8 damage)
{
if (!m_client->getServerDamage())
return;
LocalPlayer *lplayer = getLocalPlayer();
assert(lplayer);
f32 effect = lplayer->getVacuumProtection();
f32 f_damage = damage;
if (damage > 0 && effect > 0.0) {
f_damage -= f_damage*effect;
ClientEnvEvent event;
event.type = CEE_PLAYER_WEARCLOTHES;
event.player_wear.amount = damage*(500*(2.0-effect));
m_client_event_queue.push_back(event);
if (f_damage < 1.0 && f_damage > 0.0) {
damage = 1.0/f_damage;
if (myrand_range(0,damage) == 0)
f_damage = 1.0;
}
damage = f_damage;
if (damage < 1)
return;
}
if (lplayer->hp > damage) {
lplayer->hp -= damage;
}else{
lplayer->hp = 0;
}
ClientEnvEvent event;
event.type = CEE_PLAYER_DAMAGE;
event.player_damage.amount = damage;
m_client_event_queue.push_back(event);
}
void ClientEnvironment::damageLocalPlayerWithSuffocation(u8 damage)
{
if (!m_client->getServerSuffocation())
return;
LocalPlayer *lplayer = getLocalPlayer();
assert(lplayer);
f32 effect = lplayer->getSuffocationProtection();
f32 f_damage = damage;
if (damage > 0 && effect > 0.0) {
f_damage -= f_damage*effect;
ClientEnvEvent event;
event.type = CEE_PLAYER_WEARCLOTHES;
event.player_wear.amount = damage*(500*(2.0-effect));
event.player_wear.amount = damage*(100*(2.0-effect));
m_client_event_queue.push_back(event);
if (f_damage < 1.0 && f_damage > 0.0) {
damage = 1.0/f_damage;
@ -4258,7 +4150,12 @@ void ClientEnvironment::damageLocalPlayerWithSuffocation(u8 damage)
}
ClientEnvEvent event;
event.type = CEE_PLAYER_SUFFOCATE;
if (type == DAMAGE_AIR) {
event.type = CEE_PLAYER_SUFFOCATE;
}else{
lplayer->addDamage(area,type,damage);
event.type = CEE_PLAYER_DAMAGE;
}
event.player_damage.amount = damage;
m_client_event_queue.push_back(event);
}

View File

@ -559,11 +559,7 @@ public:
/*
Callbacks for activeobjects
*/
void damageLocalPlayer(u8 damage);
void damageLocalPlayerWithArmour(u8 damage);
void damageLocalPlayerWithWarmth(u8 damage);
void damageLocalPlayerWithVacuum(u8 damage);
void damageLocalPlayerWithSuffocation(u8 damage);
void damageLocalPlayer(u8 area, u8 type, u8 damage);
/*
Client likes to call these

View File

@ -2305,6 +2305,8 @@ void the_game(
&local_inventory,
client.getServerDamage(),
client.getHP(),
(p->last_damage&0xFF00)>>8,
(p->last_damage&0x00FF),
p->cold_effectf,
client.getServerSuffocation(),
client.getAir(),

View File

@ -369,12 +369,14 @@ void hud_draw(
bool show_index,
Inventory *inventory,
bool have_health,
s32 halfheartcount,
s32 health,
u8 damage_type,
u8 damage_pos,
float cold_boost,
bool have_suffocation,
s32 halfbubblecount,
s32 air,
bool have_hunger,
s32 halfhungercount,
s32 hunger,
float energy,
float energy_boost,
int crosshair,
@ -570,10 +572,10 @@ void hud_draw(
// health
if (have_health) {
int c = 55+(halfheartcount*10);
int c = 55+(health*2);
float e = 0.0;
if (halfheartcount > 0.0)
e = energy/((float)halfheartcount/100.0);
if (health > 0.0)
e = energy/((float)health/100.0);
if (e > 100.0)
e = 100.0;
if (e < 0.0)
@ -601,7 +603,7 @@ void hud_draw(
draw_image(driver,texture,color,rect,NULL,NULL);
}
std::wstring txt = itows(halfheartcount*5);
std::wstring txt = itows(health);
txt += L"%";
v2u32 dim = font->getDimension(txt.c_str());
@ -613,16 +615,71 @@ void hud_draw(
sdim
);
font->draw(txt.c_str(), rect2, video::SColor(255,255,255,255), false, false, NULL);
{
char* image[8] = {
(char*)"body_feet.png",
(char*)"body_lleg.png",
(char*)"body_rleg.png",
(char*)"body_torso.png",
(char*)"body_hands.png",
(char*)"body_larm.png",
(char*)"body_rarm.png",
(char*)"body_head.png"
};
for (int i=0; i<8; i++) {
u8 a = (1<<i);
u8 c = 255;
if ((damage_pos&a) == a)
c = 0;
const video::SColor color(255,255,c,c);
video::ITexture *texture = driver->getTexture(getTexturePath(image[i]).c_str());
core::rect<s32> rect(20,screensize.Y-182,52,screensize.Y-118);
draw_image(driver,texture,color,rect,NULL,NULL);
}
}
{
char* damage_types[] = {
(char*)"",
gettext("Unknown"),
gettext("Fall"),
gettext("Exposure"),
gettext("Cold"),
gettext("Attack"),
gettext("Space"),
gettext("Hunger"),
gettext("Air"),
gettext("Lava"),
gettext("Cactus"),
gettext("Fire"),
gettext("TNT"),
gettext("Steam"),
gettext("Poison")
};
std::wstring t = narrow_to_wide(damage_types[damage_type]);
v2u32 dim = font->getDimension(t.c_str());
v2s32 sdim(dim.X,dim.Y);
v2s32 p(52,screensize.Y-150);
p.Y -= sdim.Y/2;
core::rect<s32> rect2(
p,
sdim
);
font->draw(t.c_str(), rect2, video::SColor(255,255,255,255), false, false, NULL);
}
}
// air
if (have_suffocation && halfbubblecount<20) {
int c = 55+(halfbubblecount*10);
if (have_suffocation && air < 100) {
int c = 55+(air*2);
const video::SColor color(255,255,c,c);
video::ITexture *texture = driver->getTexture(getTexturePath("bubble.png").c_str());
core::rect<s32> rect(100,screensize.Y-68,132,screensize.Y-36);
draw_image(driver,texture,color,rect,NULL,NULL);
std::wstring txt = itows(halfbubblecount*5);
std::wstring txt = itows(air);
txt += L"%";
v2u32 dim = font->getDimension(txt.c_str());
@ -637,13 +694,13 @@ void hud_draw(
}
// hunger
if (have_hunger) {
int c = 55+(halfhungercount*10);
int c = 55+(hunger*2);
const video::SColor color(255,255,c,c);
video::ITexture *texture = driver->getTexture(getTexturePath("harvested_carrot.png").c_str());
core::rect<s32> rect(36,screensize.Y-68,68,screensize.Y-36);
draw_image(driver,texture,color,rect,NULL,NULL);
std::wstring txt = itows(halfhungercount*5);
std::wstring txt = itows(hunger);
txt += L"%";
v2u32 dim = font->getDimension(txt.c_str());
@ -833,7 +890,7 @@ void hud_draw(
core::rect<s32> rect(x_off+132,screensize.Y-36,x_off+164,screensize.Y-4);
draw_image(driver,texture,color,rect,NULL,NULL);
std::wstring txt = itows(halfhungercount*5);
std::wstring txt = itows(hunger);
txt += L"%";
v2u32 dim = font->getDimension(txt.c_str());
@ -858,7 +915,7 @@ void hud_draw(
core::rect<s32> rect(x_off+132,screensize.Y-36,x_off+164,screensize.Y-4);
draw_image(driver,texture,color,rect,NULL,NULL);
std::wstring txt = itows(halfhungercount*5);
std::wstring txt = itows(hunger);
txt += L"%";
v2u32 dim = font->getDimension(txt.c_str());

View File

@ -71,12 +71,14 @@ void hud_draw(
bool show_index,
Inventory *inventory,
bool have_health,
s32 halfheartcount,
s32 health,
u8 damage_type,
u8 damage_pos,
float cold_boost,
bool have_suffocation,
s32 halfbubblecount,
s32 air,
bool have_hunger,
s32 halfhungercount,
s32 hunger,
float energy,
float energy_boost,
int crosshair,

View File

@ -453,20 +453,16 @@ bool CraftItem::use(ServerEnvironment *env, Player *player)
bool used = false;
CraftItemFeatures f = content_craftitem_features(m_content);
if (f.consumable) {
if (f.hunger_effect && (f.health_effect < 1 || player->hunger < 20)) {
if (player->hunger + f.hunger_effect > 20) {
player->hunger = 20;
if (f.hunger_effect && (f.health_effect < 1 || player->hunger < 100)) {
if (player->hunger + f.hunger_effect > 100) {
player->hunger = 100;
}else{
player->hunger += f.hunger_effect;
}
used = true;
}
if (f.health_effect < 0 || (!used && f.health_effect > 0)) {
if (player->hp + f.health_effect > 20) {
player->hp = 20;
}else{
player->hp += f.health_effect;
}
player->addHealth(f.health_effect);
used = true;
}
if (f.cold_effect) {

View File

@ -3795,8 +3795,8 @@ void ClientMap::renderPostFx()
if (m_client->getServerSuffocation()) {
u16 a = m_client->getAir();
if (a < 18) {
u8 c = 255-(a*14);
if (a < 50) {
u8 c = 255-(a*5);
const video::SColor color(c,255,255,255);
const video::SColor colors[] = {color,color,color,color};
std::string tex = getTexturePath("low_air.png");

View File

@ -1823,7 +1823,6 @@ void make_block(BlockMakeData *data)
u32 current_depth = 0;
bool air_detected = false;
bool water_detected = false;
bool have_clay = false;
// Use fast index incrementing
s16 start_y = node_max.Y+2;

View File

@ -595,7 +595,7 @@ struct ContentFeatures
hardness = 1.0;
pressure_type = CST_MOVABLE;
damage_per_second = 0;
suffocation_per_second = 4;
suffocation_per_second = 20;
warmth_per_second = 0;
pressure_per_second = 0;
home_node = -1;

View File

@ -51,11 +51,15 @@ Player::Player():
in_bed(false),
wake_timeout(0.0),
craftresult_is_preview(true),
hp(20),
air(20),
hunger(20),
health(100),
air(100),
hunger(100),
energy_effect(0),
cold_effect(0),
dirt(0),
wet(0),
blood(0),
last_damage(0),
peer_id(PEER_ID_INEXISTENT),
m_selected_item(0),
m_pitch(0),
@ -213,7 +217,7 @@ void Player::serialize(std::ostream &os)
args.setFloat("yaw", m_yaw);
args.setV3F("position", m_position);
args.setBool("craftresult_is_preview", craftresult_is_preview);
args.setS32("hp", hp);
args.setS32("health", health);
args.setS32("air", air);
args.setS32("hunger", hunger);
if (m_hashome)
@ -263,20 +267,32 @@ void Player::deSerialize(std::istream &is)
}else{
craftresult_is_preview = true;
}
if (args.exists("hp")) {
hp = args.getS32("hp");
if (args.exists("health")) {
health = args.getS32("health");
if (args.exists("air")) {
air = args.getS32("air");
}else{
air = 100;
}
if (args.exists("hunger")) {
hunger = args.getS32("hunger");
}else{
hunger = 100;
}
}else if (args.exists("hp")) {
health = 5*args.getS32("hp");
if (args.exists("air")) {
air = 5*args.getS32("air");
}else{
air = 100;
}
if (args.exists("hunger")) {
hunger = 5*args.getS32("hunger");
}else{
hunger = 100;
}
}else{
hp = 20;
}
if (args.exists("air")) {
air = args.getS32("air");
}else{
air = 20;
}
if (args.exists("hunger")) {
hunger = args.getS32("hunger");
}else{
hunger = 20;
health = 100;
}
if (args.exists("home")) {
m_home = args.getV3F("home");
@ -1106,11 +1122,11 @@ void LocalPlayer::applyControl(float dtime)
}
}else{
if (energy_effectf) {
if (m_energy < hp)
m_energy += dtime*5.0;
if (m_energy < health)
m_energy += dtime*25.0;
}else if (control.digging) {
m_energy -= dtime*0.2;
}else if (m_energy < hp) {
m_energy -= dtime;
}else if (m_energy < health) {
if (speed.X || speed.Y || speed.Z) {
m_energy += dtime*((float)hunger/30.0);
}else{
@ -1123,8 +1139,8 @@ void LocalPlayer::applyControl(float dtime)
speed = speed.normalize() * walkspeed_max;
}
}
if (m_energy > hp) {
m_energy = hp;
if (m_energy > health) {
m_energy = health;
}else if (m_energy < -0.1) {
m_can_use_energy = false;
m_energy = -0.1;
@ -1138,7 +1154,7 @@ void LocalPlayer::applyControl(float dtime)
m_low_energy_effect = g_sound->playSound(snd,true);
}
}else if (m_energy > 1.8) {
}else if (m_energy > 9.8) {
m_can_use_energy = true;
if (g_sound && m_low_energy_effect) {
g_sound->stopSound(m_low_energy_effect);

View File

@ -65,6 +65,22 @@
#define PLAYER_HEAD 0x80
#define PLAYER_ALL 0xFF
#define DAMAGE_NONE 0x00
#define DAMAGE_UNKNOWN 0x01
#define DAMAGE_FALL 0x02
#define DAMAGE_EXPOSURE 0x03
#define DAMAGE_COLD 0x04
#define DAMAGE_ATTACK 0x05
#define DAMAGE_SPACE 0x06
#define DAMAGE_HUNGER 0x07
#define DAMAGE_AIR 0x08
#define DAMAGE_LAVA 0x09
#define DAMAGE_CACTUS 0x0A
#define DAMAGE_FIRE 0x0B
#define DAMAGE_TNT 0x0C
#define DAMAGE_STEAM 0x0D
#define DAMAGE_POISON 0x0E
class Map;
class Player
@ -213,81 +229,142 @@ public:
bool craftresult_is_preview;
u16 hp;
u16 health;
u16 air;
u16 hunger;
u16 energy_effect;
u16 cold_effect;
u8 dirt;
u8 wet;
float wet_dtime;
u8 blood;
void addDirt(u8 area)
{
dirt |= area;
}
void addBlood(u8 area)
{
blood |= area;
}
void addWater(u8 area)
{
wet |= area;
dirt &= ~area;
blood &= ~area;
}
u16 last_damage;
void addDamage(u8 area, u8 type, u16 amount)
{
last_damage = (type<<8)|area;
if (amount > health) {
health = 0;
}else{
health -= amount;
}
}
void addHealth(u16 amount)
{
last_damage = 0;
health += amount;
if (health > 100)
health = 100;
}
u16 peer_id;
bool getHome(s8 i, v3f &h);
void setHome(s8 i, v3f h);
void unsetHome(s8 i);
f32 getArmourProtection()
f32 getProtection(u8 area, u8 type)
{
InventoryList *l;
InventoryItem *i;
f32 v = 0;
const char* list[7] = {"hat","shirt","jacket","decorative","belt","pants","boots"};
switch (type) {
case DAMAGE_FALL:
l = inventory.getList("boots");
if (l == NULL)
return 0;
i = l->getItem(0);
if (i == NULL)
return 0;
return content_clothesitem_features(i->getContent()).armour;
break;
case DAMAGE_AIR:
l = inventory.getList("hat");
if (l == NULL)
return 0;
i = l->getItem(0);
if (i == NULL)
return 0;
return content_clothesitem_features(i->getContent()).suffocate;
break;
default:;
}
for (int j=0; j<7; j++) {
InventoryList *l = inventory.getList(list[j]);
if (area && area != PLAYER_ALL) {
switch (area) {
case PLAYER_FEET:
if (j != 6)
continue;
break;
case PLAYER_LLEG:
case PLAYER_RLEG:
if (j != 5 && j != 6)
continue;
break;
case PLAYER_TORSO:
if (j != 1)
continue;
break;
case PLAYER_HANDS:
case PLAYER_LARM:
case PLAYER_RARM:
if (j != 2)
continue;
break;
case PLAYER_HEAD:
if (j != 0)
continue;
break;
default:;
}
}
l = inventory.getList(list[j]);
if (l == NULL)
continue;
InventoryItem *i = l->getItem(0);
i = l->getItem(0);
if (i == NULL)
continue;
v += content_clothesitem_features(i->getContent()).armour;
switch (type) {
case DAMAGE_TNT:
case DAMAGE_FIRE:
case DAMAGE_ATTACK:
case DAMAGE_CACTUS:
v += content_clothesitem_features(i->getContent()).armour;
break;
case DAMAGE_COLD:
v += content_clothesitem_features(i->getContent()).warmth;
break;
case DAMAGE_SPACE:
v += content_clothesitem_features(i->getContent()).vacuum;
break;
default:;
}
}
if (v > 1.0)
return 1.0;
return v;
}
f32 getWarmthProtection()
{
f32 v = 0;
const char* list[7] = {"hat","shirt","jacket","decorative","belt","pants","boots"};
if (cold_effect)
return 1.0;
for (int j=0; j<7; j++) {
InventoryList *l = inventory.getList(list[j]);
if (l == NULL)
continue;
InventoryItem *i = l->getItem(0);
if (i == NULL)
continue;
v += content_clothesitem_features(i->getContent()).warmth;
}
if (v > 1.0)
return 1.0;
return v;
}
f32 getVacuumProtection()
{
f32 v = 0;
const char* list[7] = {"hat","shirt","jacket","decorative","belt","pants","boots"};
for (int j=0; j<7; j++) {
InventoryList *l = inventory.getList(list[j]);
if (l == NULL)
continue;
InventoryItem *i = l->getItem(0);
if (i == NULL)
continue;
v += content_clothesitem_features(i->getContent()).vacuum;
}
if (v > 1.0)
return 1.0;
return v;
}
f32 getSuffocationProtection()
{
InventoryList *l = inventory.getList("hat");
if (l == NULL)
return 0;
InventoryItem *i = l->getItem(0);
if (i == NULL)
return 0;
return content_clothesitem_features(i->getContent()).suffocate;
}
// character def used for skin creation and model scaling
virtual void setCharDef(std::string d) {m_character = d;}

View File

@ -1979,7 +1979,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
SendPlayerItems();
// Send HP
SendPlayerHP(player);
SendPlayerState(player);
// Send time of day
{
@ -2170,7 +2170,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
return;
// Track changes super-crappily
u16 oldhp = player->hp;
u16 oldhp = player->health;
u16 oldair = player->air;
u16 oldhunger = player->hunger;
@ -2185,8 +2185,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
SendInventory(peer_id);
// Send back stuff
if (player->hp != oldhp || player->air != oldair || player->hunger != oldhunger || player->energy_effect || player->cold_effect)
SendPlayerHP(player);
if (player->health != oldhp || player->air != oldair || player->hunger != oldhunger || player->energy_effect || player->cold_effect)
SendPlayerState(player);
}
break;
case TOSERVER_PLAYERPOS:
@ -2396,7 +2396,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
<<obj->getId()<<std::endl;
// Track changes super-crappily
u16 oldhp = player->hp;
u16 oldhp = player->health;
u16 oldair = player->air;
u16 oldhunger = player->hunger;
@ -2407,8 +2407,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
}
// Send back stuff
if (player->hp != oldhp || player->air != oldair || player->hunger != oldhunger)
SendPlayerHP(player);
if (player->health != oldhp || player->air != oldair || player->hunger != oldhunger)
SendPlayerState(player);
}
}
break;
@ -4183,7 +4183,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
}
if (!damage && !suffocate && !hunger) {
SendPlayerHP(player);
SendPlayerState(player);
}else{
HandlePlayerHP(player, damage, suffocate, hunger);
}
@ -4613,7 +4613,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
break;
case TOSERVER_RESPAWN:
{
if(player->hp != 0)
if(player->health != 0)
return;
RespawnPlayer(player);
@ -4827,15 +4827,29 @@ void Server::deletingPeer(con::Peer *peer, bool timeout)
Static send methods
*/
void Server::SendHP(con::Connection &con, u16 peer_id, u8 hp, u8 air, u8 hunger, u16 energy_effect, u16 cold_effect)
void Server::SendState(
con::Connection &con,
u16 peer_id,
u8 health,
u8 air,
u8 hunger,
u8 dirt,
u8 wet,
u8 blood,
u16 energy_effect,
u16 cold_effect
)
{
DSTACK(__FUNCTION_NAME);
std::ostringstream os(std::ios_base::binary);
writeU16(os, TOCLIENT_PLAYERHP);
writeU8(os, hp);
writeU16(os, TOCLIENT_PLAYERSTATE);
writeU8(os, health);
writeU8(os, air);
writeU8(os, hunger);
writeU8(os, dirt);
writeU8(os, wet);
writeU8(os, blood);
writeU16(os, energy_effect);
writeU16(os, cold_effect);
@ -5159,18 +5173,29 @@ void Server::BroadcastChatMessage(const std::wstring &message)
}
}
void Server::SendPlayerHP(Player *player)
void Server::SendPlayerState(Player *player)
{
u8 hp = player->hp;
u8 hp = player->health;
u8 air = player->air;
u8 hunger = player->hunger;
if (hp < 20 && !g_settings->getBool("enable_damage"))
hp = 20;
if (air < 20 && !g_settings->getBool("enable_suffocation"))
air = 20;
if (hunger < 20 && !g_settings->getBool("enable_hunger"))
hunger = 20;
SendHP(m_con, player->peer_id, hp,air,hunger,player->energy_effect,player->cold_effect);
if (hp < 100 && !g_settings->getBool("enable_damage"))
hp = 100;
if (air < 100 && !g_settings->getBool("enable_suffocation"))
air = 100;
if (hunger < 100 && !g_settings->getBool("enable_hunger"))
hunger = 100;
SendState(
m_con,
player->peer_id,
hp,
air,
hunger,
player->dirt,
player->wet,
player->blood,
player->energy_effect,
player->cold_effect
);
player->energy_effect = 0;
player->cold_effect = 0;
}
@ -5514,30 +5539,31 @@ void Server::HandlePlayerHP(Player *player, s16 damage, s16 suffocate, s16 hunge
{
if (player->air > suffocate) {
player->air -= suffocate;
if (player->air > 20)
player->air = 20;
if (player->air > 100)
player->air = 100;
}else{
damage += suffocate-player->air;
player->air = 0;
}
if (player->hunger > hunger) {
player->hunger -= hunger;
if (player->hunger > 20)
player->hunger = 20;
if (player->hunger > 100)
player->hunger = 100;
}else{
damage += hunger-player->hunger;
player->hunger = 0;
}
if (player->hp > damage) {
player->hp -= damage;
if (player->hp > 20)
player->hp = 20;
SendPlayerHP(player);
player->addDamage(PLAYER_ALL,DAMAGE_UNKNOWN,damage);
if (player->health > 0) {
SendPlayerState(player);
}else{
infostream<<"Server::HandlePlayerHP(): Player "
<<player->getName()<<" dies"<<std::endl;
player->hp = 0;
player->health = 0;
player->dirt = 0;
player->wet = 0;
player->blood = 0;
//TODO: Throw items around
if (g_settings->getBool("death_drops_inv")) {
@ -5636,7 +5662,7 @@ void Server::HandlePlayerHP(Player *player, s16 damage, s16 suffocate, s16 hunge
return;
}
SendPlayerHP(player);
SendPlayerState(player);
RemoteClient *client = getClient(player->peer_id);
if (client->net_proto_version >= 3) {
@ -5653,11 +5679,14 @@ void Server::RespawnPlayer(Player *player)
if (!player->getHome(PLAYERFLAG_HOME,pos))
pos = findSpawnPos(m_env.getServerMap());
player->setPosition(pos);
player->hp = 20;
player->air = 20;
player->hunger = 20;
player->health = 100;
player->air = 100;
player->hunger = 100;
player->dirt = 0;
player->wet = 0;
player->blood = 0;
SendMovePlayer(player);
SendPlayerHP(player);
SendPlayerState(player);
}
void Server::UpdateCrafting(u16 peer_id)

View File

@ -489,7 +489,18 @@ private:
Static send methods
*/
static void SendHP(con::Connection &con, u16 peer_id, u8 hp, u8 air, u8 hunger, u16 energy_effect, u16 cold_effect);
static void SendState(
con::Connection &con,
u16 peer_id,
u8 health,
u8 air,
u8 hunger,
u8 dirt,
u8 wet,
u8 blood,
u16 energy_effect,
u16 cold_effect
);
static void SendAccessDenied(con::Connection &con, u16 peer_id,
const std::wstring &reason);
static void SendDeathscreen(con::Connection &con, u16 peer_id,
@ -511,7 +522,7 @@ private:
void SendPlayerItems(Player *player);
void SendChatMessage(u16 peer_id, const std::wstring &message);
void BroadcastChatMessage(const std::wstring &message);
void SendPlayerHP(Player *player);
void SendPlayerState(Player *player);
// tell the client what kind of game is being played
void SendSettings(Player *player);
/*
@ -552,7 +563,7 @@ private:
std::string getPlayerName(u16 peer_id)
{
Player *player = m_env.getPlayer(peer_id);
if(player == NULL)
if (player == NULL)
return "[id="+itos(peer_id);
return player->getName();
}