make tool wear and usage a bit easier to understand pt1

This commit is contained in:
darkrose 2017-05-08 00:37:23 +10:00
parent 0e6b4ff80b
commit 0f57b18e0e
7 changed files with 679 additions and 621 deletions

View File

@ -1398,21 +1398,13 @@ u16 MobSAO::punch(content_t punch_item, v3f dir, const std::string &playername)
}
sendPosition();
tooluse_t usage;
u16 amount = 2;
if (f.type == TT_SWORD) {
amount = 4*((f.hardness/100)+1);
wear = 65535/f.hardness;
}else if (f.type == TT_CLUB) {
amount = 2*((f.hardness/100)+1);
wear = 65535/f.hardness;
}else if (f.type == TT_SPEAR) {
amount = 3*((f.hardness/100)+1);
wear = 65535/f.hardness;
}else if (f.type == TT_AXE || f.type == TT_PICK) {
amount = ((f.hardness/200)+1);
if (!get_tool_use(&usage,m_content,0,punch_item,0)) {
if (usage.diggable)
doDamage(usage.data);
wear = usage.wear;
}
doDamage(amount);
}else if (m.punch_action == MPA_DIE) {
m_hp = 0;
m_removed = true;

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,12 @@ enum ToolType {
TT_CLUB
};
typedef struct diginfo_s {
uint16_t uses;
float time;
uint8_t level;
} diginfo_t;
struct ToolItemFeatures {
content_t content;
std::string texture;
@ -48,14 +54,10 @@ struct ToolItemFeatures {
bool has_rotate_effect;
// whether this tool can start fires
bool has_fire_effect;
// digging info for this tool
diginfo_t diginfo;
// the type of this tool
ToolType type;
// the hardness of this tool
f32 hardness;
// the dig time of this tool
f32 dig_time;
// the level of the tool, this affects the amount of minerals etc.
u8 level;
// the data value of this item
ContentParamType param_type;
// used for eg. bows throwing an arrow
@ -83,55 +85,46 @@ struct ToolItemFeatures {
has_rotate_effect(false),
has_fire_effect(false),
type(TT_NONE),
hardness(0.),
dig_time(3.),
level(0),
param_type(CPT_NONE),
thrown_item(CONTENT_IGNORE),
onplace_replace_item(CONTENT_IGNORE),
onplace_node(CONTENT_IGNORE)
{}
};
struct DiggingProperties
{
DiggingProperties():
diggable(false),
time(0.0),
wear(0)
{
diginfo.uses = 256;
diginfo.time = 4.0;
diginfo.level = 0;
}
DiggingProperties(bool a_diggable, float a_time, u16 a_wear):
diggable(a_diggable),
time(a_time),
wear(a_wear)
{
}
bool diggable;
// Digging time in seconds
float time;
// Caused wear
u16 wear;
};
typedef struct tooluse_s {
bool diggable;
// Digging time in seconds or hit damage
float data;
// Caused wear
uint16_t wear;
// delay till tool can be used again
float delay;
} tooluse_t;
// For getting the default properties, set toolid=CONTENT_IGNORE
DiggingProperties getDiggingProperties(content_t material, u8 mineral, content_t toolid, u16 data=0);
int get_tool_use(tooluse_t *info, content_t target, uint16_t data, content_t toolid, uint16_t tooldata);
std::string toolitem_overlay(content_t content, std::string ol);
void content_toolitem_init();
ToolItemFeatures & content_toolitem_features(content_t i);
ToolItemFeatures & content_toolitem_features(std::string subname);
#define CONTENT_TOOLITEM_SMALL_PICK (CONTENT_TOOLITEM_MASK | 0x01)
#define CONTENT_TOOLITEM_STPICK (CONTENT_TOOLITEM_MASK | 0x02)
#define CONTENT_TOOLITEM_STONEPICK (CONTENT_TOOLITEM_MASK | 0x02)
#define CONTENT_TOOLITEM_STEELPICK (CONTENT_TOOLITEM_MASK | 0x03)
#define CONTENT_TOOLITEM_CREATIVEPICK (CONTENT_TOOLITEM_MASK | 0x04)
#define CONTENT_TOOLITEM_TROWEL (CONTENT_TOOLITEM_MASK | 0x05)
#define CONTENT_TOOLITEM_STSHOVEL (CONTENT_TOOLITEM_MASK | 0x06)
#define CONTENT_TOOLITEM_STONESHOVEL (CONTENT_TOOLITEM_MASK | 0x06)
#define CONTENT_TOOLITEM_STEELSHOVEL (CONTENT_TOOLITEM_MASK | 0x07)
#define CONTENT_TOOLITEM_SMALL_AXE (CONTENT_TOOLITEM_MASK | 0x08)
#define CONTENT_TOOLITEM_STAXE (CONTENT_TOOLITEM_MASK | 0x09)
#define CONTENT_TOOLITEM_STONEAXE (CONTENT_TOOLITEM_MASK | 0x09)
#define CONTENT_TOOLITEM_STEELAXE (CONTENT_TOOLITEM_MASK | 0x0A)
#define CONTENT_TOOLITEM_CLUB (CONTENT_TOOLITEM_MASK | 0x0B)
#define CONTENT_TOOLITEM_STSWORD (CONTENT_TOOLITEM_MASK | 0x0C)
#define CONTENT_TOOLITEM_STONESWORD (CONTENT_TOOLITEM_MASK | 0x0C)
#define CONTENT_TOOLITEM_STEELSWORD (CONTENT_TOOLITEM_MASK | 0x0D)
#define CONTENT_TOOLITEM_STEELSHEARS (CONTENT_TOOLITEM_MASK | 0x0E)
#define CONTENT_TOOLITEM_WBUCKET (CONTENT_TOOLITEM_MASK | 0x0F)

View File

@ -861,17 +861,12 @@ void the_game(
core::list<float> frametime_log;
float nodig_delay_counter = 0.0;
float action_delay_counter = 0.0;
float dig_time = 0.0;
v3s16 nodepos_old(-32768,-32768,-32768);
float use_delay_counter = 0.5;
float damage_flash_timer = 0;
const float object_hit_delay = 0.5;
float object_hit_delay_timer = 0.0;
bool invert_mouse = g_settings->getBool("invert_mouse");
bool respawn_menu_active = false;
@ -1018,8 +1013,6 @@ void the_game(
/* Run timers */
object_hit_delay_timer -= dtime;
g_profiler->add("Elapsed time", dtime);
g_profiler->avg("FPS", 1./dtime);
@ -1551,7 +1544,12 @@ void the_game(
InventoryItem *wield = (InventoryItem*)client.getLocalPlayer()->getWieldItem();
InventoryList *ilist;
if (
printf("action_delay_counter = %f\n",action_delay_counter);
if (action_delay_counter > 0.0) {
action_delay_counter -= dtime;
}else if (
wield
&& (
content_craftitem_features(wield->getContent()).thrown_item != CONTENT_IGNORE
@ -1601,26 +1599,28 @@ void the_game(
infotext = narrow_to_wide(selected_active_object->infoText());
if (input->getLeftState()) {
bool do_punch = false;
bool do_punch_damage = false;
if (object_hit_delay_timer <= 0.0){
do_punch = true;
do_punch_damage = true;
object_hit_delay_timer = object_hit_delay;
tooluse_t usage;
content_t toolid = CONTENT_IGNORE;
u16 tooldata = 0;
InventoryList *mlist = local_inventory.getList("main");
if (mlist != NULL) {
InventoryItem *item = mlist->getItem(g_selected_item);
if (item && (item->getContent()&CONTENT_TOOLITEM_MASK) == CONTENT_TOOLITEM_MASK) {
ToolItem *titem = (ToolItem*)item;
toolid = titem->getContent();
tooldata = titem->getData();
}
}
if (input->getLeftClicked()) {
do_punch = true;
}
if (do_punch) {
infostream<<"Left-clicked object"<<std::endl;
if (!get_tool_use(&usage,selected_active_object->getContent(),0,toolid,tooldata)) {
left_punch = true;
}
if (do_punch_damage) {
client.clickActiveObject(0, selected_active_object->getId(), g_selected_item);
action_delay_counter = usage.delay;
}
}else if (input->getRightClicked()) {
infostream<<"Right-clicked object"<<std::endl;
client.clickActiveObject(1, selected_active_object->getId(), g_selected_item);
action_delay_counter = 0.25;
}
}else{ // selected_object == NULL
/*
@ -1671,93 +1671,80 @@ void the_game(
if (!highlight_selected_node)
hilightboxes.push_back(nodehilightbox);
if (nodig_delay_counter > 0.0) {
nodig_delay_counter -= dtime;
}else{
if (nodepos != nodepos_old) {
infostream<<"Pointing at ("<<nodepos.X<<","
<<nodepos.Y<<","<<nodepos.Z<<")"<<std::endl;
if (nodepos != nodepos_old) {
infostream<<"Pointing at ("<<nodepos.X<<","
<<nodepos.Y<<","<<nodepos.Z<<")"<<std::endl;
if (nodepos_old != v3s16(-32768,-32768,-32768)) {
dig_time = 0.0;
nodepos_old = v3s16(-32768,-32768,-32768);
if (nodepos_old != v3s16(-32768,-32768,-32768)) {
dig_time = 0.0;
nodepos_old = v3s16(-32768,-32768,-32768);
}
}
if (input->getLeftClicked() || (input->getLeftState() && nodepos != nodepos_old)) {
infostream<<"Started digging"<<std::endl;
client.groundAction(0, nodepos, neighbourpos, g_selected_item);
}
if (input->getLeftClicked())
selected_node_crack = 0;
if (input->getLeftState()) {
MapNode n = client.getNode(nodepos);
// Get tool name. Default is "" = bare hands
content_t toolid = CONTENT_IGNORE;
u16 tooldata = 0;
InventoryList *mlist = local_inventory.getList("main");
if (mlist != NULL) {
InventoryItem *item = mlist->getItem(g_selected_item);
if (item && (item->getContent()&CONTENT_TOOLITEM_MASK) == CONTENT_TOOLITEM_MASK) {
ToolItem *titem = (ToolItem*)item;
toolid = titem->getContent();
tooldata = titem->getData();
}
}
if (input->getLeftClicked() || (input->getLeftState() && nodepos != nodepos_old)) {
infostream<<"Started digging"<<std::endl;
client.groundAction(0, nodepos, neighbourpos, g_selected_item);
}
if (input->getLeftClicked())
selected_node_crack = 0;
if (input->getLeftState()) {
MapNode n = client.getNode(nodepos);
// Get digging properties for material and tool
content_t material = n.getContent();
uint16_t mineral = n.getMineral();
tooluse_t usage;
// Get tool name. Default is "" = bare hands
content_t toolid = CONTENT_IGNORE;
u16 tooldata = 0;
InventoryList *mlist = local_inventory.getList("main");
if (mlist != NULL) {
InventoryItem *item = mlist->getItem(g_selected_item);
if (item && (item->getContent()&CONTENT_TOOLITEM_MASK) == CONTENT_TOOLITEM_MASK) {
ToolItem *titem = (ToolItem*)item;
toolid = titem->getContent();
tooldata = titem->getData();
}
}
if (get_tool_use(&usage,material,mineral,toolid,tooldata))
usage.diggable = false;
// Get digging properties for material and tool
content_t material = n.getContent();
u8 mineral = n.getMineral();
DiggingProperties prop = getDiggingProperties(material, mineral, toolid, tooldata);
float dig_time_complete = 0.0;
float dig_time_complete = 0.0;
if (!usage.diggable) {
dig_time_complete = 10000000.0;
}else{
dig_time_complete = usage.data;
if (enable_particles)
addPunchingParticles(smgr, player, nodepos, content_features(n).tiles);
if (prop.diggable == false) {
dig_time_complete = 10000000.0;
if (dig_time_complete >= 0.001) {
selected_node_crack = (u16)((float)CRACK_ANIMATION_LENGTH
* dig_time/dig_time_complete);
}else{
dig_time_complete = prop.time;
if (enable_particles)
addPunchingParticles(smgr, player, nodepos, content_features(n).tiles);
if (dig_time_complete >= 0.001) {
selected_node_crack = (u16)((float)CRACK_ANIMATION_LENGTH
* dig_time/dig_time_complete);
}else {
// This is for torches
selected_node_crack = CRACK_ANIMATION_LENGTH;
}
if (selected_node_crack >= CRACK_ANIMATION_LENGTH) {
infostream<<"Digging completed"<<std::endl;
client.groundAction(3, nodepos, neighbourpos, g_selected_item);
selected_node_crack = 0;
client.removeNode(nodepos);
if (enable_particles)
addDiggingParticles(smgr, player, nodepos, content_features(n).tiles);
dig_time = 0.0;
nodig_delay_counter = dig_time_complete
/ (float)CRACK_ANIMATION_LENGTH;
// We don't want a corresponding delay to
// very time consuming nodes
if (nodig_delay_counter > 0.5)
nodig_delay_counter = 0.5;
// We want a slight delay to very little
// time consuming nodes
float mindelay = 0.15;
if (nodig_delay_counter < mindelay)
nodig_delay_counter = mindelay;
}
selected_node_crack = CRACK_ANIMATION_LENGTH;
}
dig_time += dtime;
if (selected_node_crack >= CRACK_ANIMATION_LENGTH) {
infostream<<"Digging completed"<<std::endl;
client.groundAction(3, nodepos, neighbourpos, g_selected_item);
selected_node_crack = 0;
client.removeNode(nodepos);
camera.setDigging(0); // left click animation
if (enable_particles)
addDiggingParticles(smgr, player, nodepos, content_features(n).tiles);
dig_time = 0.0;
action_delay_counter = usage.delay;
}
}
dig_time += dtime;
camera.setDigging(0); // left click animation
}
@ -1822,14 +1809,12 @@ void the_game(
} // selected_object == NULL
}
use_delay_counter -= dtime;
// this lets us hold down use to eat, and limits to 2 items per second
if (input->wasKeyDown(getKeySetting(VLKC_USE))) {
if (use_delay_counter <= 0.0) {
if (action_delay_counter <= 0.0) {
client.useItem();
/* TODO: this should come from content*_features */
use_delay_counter = 1.0;
action_delay_counter = 0.25;
}
}

View File

@ -543,14 +543,14 @@ std::wstring ToolItem::getGuiText()
ToolItemFeatures *f = &content_toolitem_features(m_content);
txt += f->description;
txt += L"\n\n";
txt += wgettext("Strength: ");
txt += ftows(f->hardness);
txt += wgettext("Uses: ");
txt += ftows(f->diginfo.uses);
txt += L"\n";
txt += wgettext("Speed: ");
txt += ftows(f->dig_time);
txt += ftows(f->diginfo.time);
txt += L"\n";
txt += wgettext("Level: ");
txt += itows(f->level);
txt += itows(f->diginfo.level);
if (f->fuel_time != 0.0) {
char buff[20];
txt += L"\n";

View File

@ -50,11 +50,11 @@ CraftItem *getDiggedMineralItem(u8 mineral, Player *player, InventoryItem *tool)
if (t->content == CONTENT_IGNORE && m.min_level > 0)
return NULL;
if (t->level < m.min_level)
if (t->diginfo.level < m.min_level)
return NULL;
u16 count = m.dug_count_min;
u16 count_max = t->level;
u16 count_max = t->diginfo.level;
u16 data = tool->getData();
if (data != 0) {

View File

@ -3287,21 +3287,27 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
InventoryList *mlist = player->inventory.getList("main");
if (mlist != NULL && g_settings->getBool("tool_wear")) {
InventoryItem *item = mlist->getItem(item_i);
if (item && (std::string)item->getName() == "ToolItem") {
if (item && (item->getContent()&CONTENT_TOOLITEM_MASK) == CONTENT_TOOLITEM_MASK) {
ToolItem *titem = (ToolItem*)item;
// Get digging properties for material and tool
DiggingProperties prop = getDiggingProperties(selected_content, mineral, titem->getContent(),titem->getData());
if (prop.diggable == false) {
tooluse_t usage;
if (get_tool_use(&usage,selected_content,mineral,titem->getContent(),titem->getData())) {
infostream<<"Server: WARNING: Player digged"
<<" with impossible material + tool"
<<" combination"<<std::endl;
}else{
if (!usage.diggable) {
infostream<<"Server: WARNING: Player digged"
<<" with impossible material + tool"
<<" combination"<<std::endl;
}
if (titem->addWear(prop.wear)) {
mlist->deleteItem(item_i);
}else{
mlist->addDiff(item_i,titem);
}
if (usage.wear) {
if (titem->addWear(usage.wear)) {
mlist->deleteItem(item_i);
}else{
mlist->addDiff(item_i,titem);
}
}
}
}
}
@ -3336,7 +3342,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
&& selected_node_features.ondig_special_tool == wielded_tool_features.type
&& (
selected_node_features.liquid_type != LIQUID_NONE
|| wielded_tool_features.level > 1
|| wielded_tool_features.diginfo.level > 1
)
) {
if (selected_node_features.ondig_special_tool_append != "") {
@ -3520,8 +3526,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
if (
extra_dug_s != ""
&& extra_rarity != 0
&& selected_node_features.extra_dug_item_min_level <= wielded_tool_features.level
&& selected_node_features.extra_dug_item_max_level >= wielded_tool_features.level
&& selected_node_features.extra_dug_item_min_level <= wielded_tool_features.diginfo.level
&& selected_node_features.extra_dug_item_max_level >= wielded_tool_features.diginfo.level
&& myrand_range(0,extra_rarity) == 0
) {
std::istringstream is(extra_dug_s, std::ios::binary);