add hunger, enable for survival mode

This commit is contained in:
darkrose 2014-09-22 22:43:19 +10:00
parent f542cfa84e
commit 3266833cb9
12 changed files with 131 additions and 60 deletions

View File

@ -546,7 +546,7 @@ void Client::step(float dtime)
}else if (event.type == CEE_PLAYER_DAMAGE) {
if (m_ignore_damage_timer <= 0) {
s8 damage = event.player_damage.amount;
sendDamage(damage,0);
sendDamage(damage,0,0);
// Add to ClientEvent queue
ClientEvent event;
@ -557,16 +557,33 @@ void Client::step(float dtime)
}else if (event.type == CEE_PLAYER_SUFFOCATE) {
if (m_ignore_damage_timer <= 0) {
s8 damage = event.player_damage.amount;
sendDamage(0,damage);
sendDamage(0,damage,0);
// Add to ClientEvent queue
ClientEvent event;
event.type = CE_PLAYER_SUFFOCATE;
// this will cause the damage screen to flash
// when suffocation starts effecting damage
if (getAir() < 1 && damage > 0)
event.type = CE_PLAYER_DAMAGE;
event.player_damage.amount = damage;
m_client_event_queue.push_back(event);
}
}else if (event.type == CEE_PLAYER_HUNGER) {
if (m_ignore_damage_timer <= 0) {
s8 damage = event.player_damage.amount;
sendDamage(0,0,damage);
// Add to ClientEvent queue
ClientEvent event;
event.type = CE_PLAYER_HUNGER;
// this will cause the damage screen to flash
// when hunger starts effecting damage
if (getHunger() < 1 && damage > 0)
event.type = CE_PLAYER_DAMAGE;
event.player_damage.amount = damage;
m_client_event_queue.push_back(event);
}
}
}
}
@ -1131,8 +1148,10 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
assert(player != NULL);
u8 hp = readU8(is);
u8 air = readU8(is);
u8 hunger = readU8(is);
player->hp = hp;
player->air = air;
player->hunger = hunger;
}
else if(command == TOCLIENT_INVENTORY)
{
@ -1732,7 +1751,7 @@ void Client::sendChangePassword(const std::wstring oldpassword,
}
void Client::sendDamage(s8 damage,s8 suffocate)
void Client::sendDamage(s8 damage,s8 suffocate,s8 hunger)
{
DSTACK(__FUNCTION_NAME);
std::ostringstream os(std::ios_base::binary);
@ -1740,6 +1759,7 @@ void Client::sendDamage(s8 damage,s8 suffocate)
writeU16(os, TOSERVER_PLAYERDAMAGE);
writeS8(os, damage);
writeS8(os, suffocate);
writeS8(os, hunger);
// Make data buffer
std::string s = os.str();
@ -2108,6 +2128,13 @@ u16 Client::getAir()
return player->air;
}
u16 Client::getHunger()
{
Player *player = m_env.getLocalPlayer();
assert(player != NULL);
return player->hunger;
}
void Client::setTempMod(v3s16 p, NodeMod mod)
{
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out

View File

@ -120,6 +120,7 @@ enum ClientEventType
CE_NONE,
CE_PLAYER_DAMAGE,
CE_PLAYER_SUFFOCATE,
CE_PLAYER_HUNGER,
CE_PLAYER_FORCE_MOVE,
CE_DEATHSCREEN,
};
@ -208,7 +209,7 @@ public:
void sendChatMessage(const std::wstring &message);
void sendChangePassword(const std::wstring oldpassword,
const std::wstring newpassword);
void sendDamage(s8 damage, s8 suffocate);
void sendDamage(s8 damage, s8 suffocate, s8 hunger);
void sendRespawn();
void sendWantCookie();
@ -262,6 +263,7 @@ public:
u16 getHP();
u16 getAir();
u16 getHunger();
void setTempMod(v3s16 p, NodeMod mod);
void clearTempMod(v3s16 p);

View File

@ -85,8 +85,9 @@ enum ToClientCommand
TOCLIENT_PLAYERHP = 0x26,
/*
u16 command
u8 hp
s8 hp
s8 air
s8 hunger
*/
TOCLIENT_INVENTORY = 0x27,
@ -287,8 +288,9 @@ enum ToServerCommand
TOSERVER_PLAYERDAMAGE = 0x29,
/*
u16 command
u8 damage_amount
u8 suffocate_amount
s8 damage_amount
s8 suffocate_amount
s8 hunger_amount
*/
TOSERVER_SIGNTEXT = 0x30, // Old signs

View File

@ -153,6 +153,7 @@ void set_creative_defaults(Settings *settings)
settings->setDefault("droppable_inventory", "false");
settings->setDefault("enable_damage", "false");
settings->setDefault("enable_suffocation", "false");
settings->setDefault("enable_hunger", "false");
settings->setDefault("max_mob_level", "passive");
settings->setDefault("initial_inventory", "false");
settings->setDefault("tool_wear","false");
@ -164,6 +165,7 @@ void set_adventure_defaults(Settings *settings)
settings->setDefault("droppable_inventory", "true");
settings->setDefault("enable_damage", "true");
settings->setDefault("enable_suffocation", "false");
settings->setDefault("enable_hunger", "false");
settings->setDefault("max_mob_level", "aggressive");
settings->setDefault("initial_inventory", "true");
settings->setDefault("tool_wear","true");
@ -175,6 +177,7 @@ void set_survival_defaults(Settings *settings)
settings->setDefault("droppable_inventory", "true");
settings->setDefault("enable_damage", "true");
settings->setDefault("enable_suffocation", "true");
settings->setDefault("enable_hunger", "true");
settings->setDefault("max_mob_level", "aggressive");
settings->setDefault("initial_inventory", "false");
settings->setDefault("tool_wear","true");

View File

@ -4045,6 +4045,25 @@ void ClientEnvironment::step(float dtime)
event.type = CEE_PLAYER_SUFFOCATE;
event.player_damage.amount = -20;
m_client_event_queue.push_back(event);
}else{
f32 speed = lplayer->getSpeed().getLength();
s8 hungry = 0;
s32 chance = 100;
if (speed > 1.0) {
chance = 10;
if (speed > 50.0) {
chance = 0;
hungry = 1;
}
}
if (chance && myrand()%chance == 0)
hungry = 1;
if (hungry) {
ClientEnvEvent event;
event.type = CEE_PLAYER_HUNGER;
event.player_damage.amount = hungry;
m_client_event_queue.push_back(event);
}
}
}

View File

@ -337,7 +337,8 @@ enum ClientEnvEventType
{
CEE_NONE,
CEE_PLAYER_DAMAGE,
CEE_PLAYER_SUFFOCATE
CEE_PLAYER_SUFFOCATE,
CEE_PLAYER_HUNGER
};
struct ClientEnvEvent

View File

@ -223,7 +223,7 @@ public:
*/
void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font,
v2s32 centerlowerpos, s32 imgsize, s32 itemcount,
Inventory *inventory, s32 halfheartcount, s32 halfbubblecount)
Inventory *inventory, s32 halfheartcount, s32 halfbubblecount, s32 halfhungercount)
{
InventoryList *mainlist = inventory->getList("main");
if(mainlist == NULL)
@ -286,7 +286,7 @@ void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font,
} barData[3] = {
{halfheartcount/2,halfheartcount,"heart.png",true},
{halfbubblecount/2,halfbubblecount,"bubble.png",false},
{10,0,"heart.png",false},
{halfhungercount/2,halfhungercount,"harvested_carrot.png",true},
};
v2s32 bar_base(0,-25);
for (s32 k=0; k<3; k++) {
@ -319,33 +319,6 @@ void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font,
}
bar_base.Y -= 20;
}
//if (halfbubblecount < 20) {
//video::ITexture *bubble_texture = driver->getTexture(getTexturePath("bubble.png").c_str());
//v2s32 p = pos + v2s32(0, -40);
//for (s32 i=0; i<halfbubblecount/2; i++) {
//const video::SColor color(255,255,255,255);
//const video::SColor colors[] = {color,color,color,color};
//core::rect<s32> rect(0,0,16,16);
//rect += p;
//driver->draw2DImage(bubble_texture, rect,
//core::rect<s32>(core::position2d<s32>(0,0),
//core::dimension2di(bubble_texture->getOriginalSize())),
//NULL, colors, true);
//p += v2s32(16,0);
//}
//if (halfbubblecount % 2 == 1) {
//const video::SColor color(255,255,255,255);
//const video::SColor colors[] = {color,color,color,color};
//core::rect<s32> rect(0,0,16/2,16);
//rect += p;
//core::dimension2di srcd(bubble_texture->getOriginalSize());
//srcd.Width /= 2;
//driver->draw2DImage(bubble_texture, rect,
//core::rect<s32>(core::position2d<s32>(0,0), srcd),
//NULL, colors, true);
//p += v2s32(16,0);
//}
//}
if (selected != "") {
v2u32 dim = font->getDimension(narrow_to_wide(selected).c_str());
v2s32 sdim(dim.X,dim.Y);
@ -2414,7 +2387,7 @@ void the_game(
if (show_hud) {
draw_hotbar(driver, font, v2s32(displaycenter.X, screensize.Y),
hotbar_imagesize, hotbar_itemcount, &local_inventory,
client.getHP(), client.getAir());
client.getHP(), client.getAir(), client.getHunger());
}
/*

View File

@ -249,10 +249,22 @@ bool CraftItem::use(ServerEnvironment *env, Player *player)
if (content_craftitem_features(m_content).edible) {
u16 result_count = getCount() - 1; // Eat one at a time
s16 hp_change = content_craftitem_features(m_content).edible;
if(player->hp + hp_change > 20)
player->hp = 20;
else
player->hp += hp_change;
if (hp_change) {
if (player->hunger < 20) {
if (player->hunger + hp_change > 20) {
hp_change -= 20-player->hunger;
player->hunger = 20;
}else{
player->hunger += hp_change;
hp_change = 0;
}
}
if (player->hp + hp_change > 20) {
player->hp = 20;
}else{
player->hp += hp_change;
}
}
if(result_count < 1)
return true;

View File

@ -38,6 +38,8 @@ Player::Player():
inventory_backup(NULL),
craftresult_is_preview(true),
hp(20),
air(20),
hunger(20),
peer_id(PEER_ID_INEXISTENT),
m_selected_item(0),
m_pitch(0),
@ -119,6 +121,8 @@ void Player::serialize(std::ostream &os)
args.setV3F("position", m_position);
args.setBool("craftresult_is_preview", craftresult_is_preview);
args.setS32("hp", hp);
args.setS32("air", air);
args.setS32("hunger", hunger);
if (m_hashome)
args.setV3F("home",m_home);
@ -170,6 +174,16 @@ void Player::deSerialize(std::istream &is)
}catch(SettingNotFoundException &e){
hp = 20;
}
try{
air = args.getS32("air");
}catch(SettingNotFoundException &e){
air = 20;
}
try{
hunger = args.getS32("hunger");
}catch(SettingNotFoundException &e){
hunger = 20;
}
try{
m_home = args.getV3F("home");
m_hashome = true;
@ -407,8 +421,7 @@ LocalPlayer::LocalPlayer():
// Initialize hp to 0, so that no hearts will be shown if server
// doesn't support health points
hp = 0;
// Likewise, initialize air to 20, so that no bubbles will be shown
air = 20;
hunger = 0;
}
LocalPlayer::~LocalPlayer()

View File

@ -173,6 +173,7 @@ public:
u16 hp;
u16 air;
u16 hunger;
u16 peer_id;

View File

@ -2130,7 +2130,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
/*
Check HP, respawn if necessary
*/
HandlePlayerHP(player, 0, 0);
HandlePlayerHP(player, 0, 0, 0);
/*
Print out action
@ -2381,17 +2381,17 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
actionstream<<player->getName()<<" right clicks object "
<<obj->getId()<<std::endl;
// Track hp changes super-crappily
// Track changes super-crappily
u16 oldhp = player->hp;
u16 oldair = player->air;
u16 oldhunger = player->hunger;
// Do stuff
obj->rightClick(player);
// Send back stuff
if(player->hp != oldhp)
{
if (player->hp != oldhp || player->air != oldair || player->hunger != oldhunger)
SendPlayerHP(player);
}
}
}
else if(command == TOSERVER_GROUND_ACTION)
@ -3489,7 +3489,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|| tool->getContent() != CONTENT_TOOLITEM_STEELBUCKET
) {
mlist->deleteItem(item_i);
HandlePlayerHP(player,4,0);
HandlePlayerHP(player,4,0,0);
}else{
std::string dug_s = std::string("ToolItem ") + tool->getToolName() + "_lava 1";
std::istringstream is(dug_s, std::ios::binary);
@ -4084,7 +4084,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
}
}else{
ilist->deleteItem(item_i);
HandlePlayerHP(player,4,0);
HandlePlayerHP(player,4,0,0);
UpdateCrafting(player->peer_id);
SendInventory(player->peer_id);
}
@ -4281,6 +4281,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
std::istringstream is(datastring, std::ios_base::binary);
s8 damage = readS8(is);
s8 suffocate = readS8(is);
s8 hunger = readS8(is);
if (damage && g_settings->getBool("enable_damage")) {
actionstream<<player->getName()<<" damaged by "
@ -4296,11 +4297,18 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
}else{
suffocate = 0;
}
if (hunger && g_settings->getBool("enable_hunger")) {
actionstream<<player->getName()<<" lost "
<<(int)hunger<<" hunger at "<<PP(player->getPosition()/BS)
<<std::endl;
}else{
hunger = 0;
}
if (!damage && !suffocate) {
if (!damage && !suffocate && !hunger) {
SendPlayerHP(player);
}else{
HandlePlayerHP(player, damage, suffocate);
HandlePlayerHP(player, damage, suffocate, hunger);
}
}
else if(command == TOSERVER_SIGNTEXT)
@ -4612,7 +4620,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
<<(int)damage<<" hp at "<<PP(player->getPosition()/BS)
<<std::endl;
HandlePlayerHP(player, damage, 0);
HandlePlayerHP(player, damage, 0, 0);
}else{
SendPlayerHP(player);
}
@ -4913,7 +4921,7 @@ void Server::deletingPeer(con::Peer *peer, bool timeout)
Static send methods
*/
void Server::SendHP(con::Connection &con, u16 peer_id, u8 hp, u8 air)
void Server::SendHP(con::Connection &con, u16 peer_id, u8 hp, u8 air, u8 hunger)
{
DSTACK(__FUNCTION_NAME);
std::ostringstream os(std::ios_base::binary);
@ -4921,6 +4929,7 @@ void Server::SendHP(con::Connection &con, u16 peer_id, u8 hp, u8 air)
writeU16(os, TOCLIENT_PLAYERHP);
writeU8(os, hp);
writeU8(os, air);
writeU8(os, hunger);
// Make data buffer
std::string s = os.str();
@ -5171,7 +5180,7 @@ void Server::BroadcastChatMessage(const std::wstring &message)
void Server::SendPlayerHP(Player *player)
{
SendHP(m_con, player->peer_id, player->hp, player->air);
SendHP(m_con, player->peer_id, player->hp, player->air,player->hunger);
}
void Server::SendPlayerCookie(Player *player)
@ -5451,7 +5460,7 @@ void Server::SendBlocks(float dtime)
Something random
*/
void Server::HandlePlayerHP(Player *player, s16 damage, s16 suffocate)
void Server::HandlePlayerHP(Player *player, s16 damage, s16 suffocate, s16 hunger)
{
if (player->air > suffocate) {
player->air -= suffocate;
@ -5461,6 +5470,14 @@ void Server::HandlePlayerHP(Player *player, s16 damage, s16 suffocate)
player->air = 0;
damage += suffocate-player->air;
}
if (player->hunger > hunger) {
player->hunger -= hunger;
if (player->hunger > 20)
player->hunger = 20;
}else{
player->hunger = 0;
damage += hunger-player->hunger;
}
if (player->hp > damage) {
player->hp -= damage;
if (player->hp > 20)
@ -5502,6 +5519,7 @@ void Server::RespawnPlayer(Player *player)
player->setPosition(pos);
player->hp = 20;
player->air = 20;
player->hunger = 20;
SendMovePlayer(player);
SendPlayerHP(player);
}

View File

@ -513,7 +513,7 @@ private:
Static send methods
*/
static void SendHP(con::Connection &con, u16 peer_id, u8 hp, u8 air);
static void SendHP(con::Connection &con, u16 peer_id, u8 hp, u8 air, u8 hunger);
static void SendAccessDenied(con::Connection &con, u16 peer_id,
const std::wstring &reason);
static void SendDeathscreen(con::Connection &con, u16 peer_id,
@ -558,7 +558,7 @@ private:
Something random
*/
void HandlePlayerHP(Player *player, s16 damage, s16 suffocate);
void HandlePlayerHP(Player *player, s16 damage, s16 suffocate, s16 hunger);
void RespawnPlayer(Player *player);
void UpdateCrafting(u16 peer_id);