Skip to content

Commit

Permalink
Decay time random (#4531)
Browse files Browse the repository at this point in the history
* Decay time random

* method getDefaultDuration moved to cpp

* applying changes

* missing enums

* suggestion of @ranisalt

* fix small thing
  • Loading branch information
MillhioreBT authored Mar 14, 2024
1 parent a0c0238 commit a4ba6bf
Show file tree
Hide file tree
Showing 10 changed files with 85 additions and 31 deletions.
12 changes: 6 additions & 6 deletions data/items/items.xml
Original file line number Diff line number Diff line change
Expand Up @@ -729,15 +729,15 @@
<item id="1497" article="a" name="magic wall">
<attribute key="type" value="magicfield" />
<attribute key="decayTo" value="0" />
<attribute key="duration" value="20" />
<attribute key="duration" minvalue="14" maxvalue="20" />
</item>
<item id="1498" article="a" name="magic wall">
<attribute key="type" value="magicfield" />
</item>
<item id="1499" name="rush wood">
<attribute key="type" value="magicfield" />
<attribute key="decayTo" value="0" />
<attribute key="duration" value="45" />
<attribute key="duration" minvalue="38" maxvalue="45" />
<attribute key="blocking" value="true" />
</item>
<item id="1500" article="a" name="yellow flame">
Expand Down Expand Up @@ -19687,12 +19687,12 @@
<item id="11098" article="a" name="magic wall">
<attribute key="type" value="magicfield" />
<attribute key="decayTo" value="0" />
<attribute key="duration" value="20" />
<attribute key="duration" minvalue="14" maxvalue="20" />
</item>
<item id="11099" article="a" name="rush wood">
<attribute key="type" value="magicfield" />
<attribute key="decayTo" value="0" />
<attribute key="duration" value="45" />
<attribute key="duration" minvalue="38" maxvalue="45" />
</item>
<item id="11100" article="a" name="flask with beaver bait">
<attribute key="description" value="It smells like a mixture of wood and fish. Phew." />
Expand Down Expand Up @@ -30117,12 +30117,12 @@
<item id="20669" article="a" name="magic wall">
<attribute key="type" value="magicfield" />
<attribute key="decayTo" value="0" />
<attribute key="duration" value="20" />
<attribute key="duration" minvalue="14" maxvalue="20" />
</item>
<item id="20670" name="rush wood">
<attribute key="type" value="magicfield" />
<attribute key="decayTo" value="0" />
<attribute key="duration" value="45" />
<attribute key="duration" minvalue="38" maxvalue="45" />
<attribute key="blocking" value="true" />
</item>
<item fromid="20671" toid="20691" article="a" name="basalt crystal wall" />
Expand Down
2 changes: 2 additions & 0 deletions data/lib/compat/compat.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1640,6 +1640,8 @@ function table.maxn(t)
return max
end

ItemType.getDuration = ItemType.getDurationMin

function getFormattedWorldTime()
return Game.getFormattedWorldTime()
end
2 changes: 2 additions & 0 deletions src/enums.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ enum itemAttrTypes : uint32_t
ITEM_ATTRIBUTE_STOREITEM = 1 << 25,
ITEM_ATTRIBUTE_ATTACK_SPEED = 1 << 26,
ITEM_ATTRIBUTE_OPENCONTAINER = 1 << 27,
ITEM_ATTRIBUTE_DURATION_MIN = ITEM_ATTRIBUTE_DURATION,
ITEM_ATTRIBUTE_DURATION_MAX = 1 << 28,

ITEM_ATTRIBUTE_CUSTOM = 1U << 31
};
Expand Down
18 changes: 15 additions & 3 deletions src/item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ void Item::setID(uint16_t newid)
id = newid;

const ItemType& it = Item::items[newid];
uint32_t newDuration = it.decayTime * 1000;
uint32_t newDuration = normal_random(it.decayTimeMin, it.decayTimeMax) * 1000;

if (newDuration == 0 && !it.stopTime && it.decayTo < 0) {
removeAttribute(ITEM_ATTRIBUTE_DECAYSTATE);
Expand Down Expand Up @@ -1050,13 +1050,25 @@ void Item::setUniqueId(uint16_t n)
}
}

void Item::setDefaultDuration()
{
uint32_t duration = getDefaultDurationMin();
if (uint32_t durationMax = getDefaultDurationMax()) {
duration = normal_random(duration, durationMax);
}

if (duration != 0) {
setDuration(duration);
}
}

bool Item::canDecay() const
{
if (isRemoved()) {
return false;
}

if (getDecayTo() < 0 || getDecayTime() == 0) {
if (getDecayTo() < 0 || (getDecayTimeMin() == 0 && getDecayTimeMax() == 0)) {
return false;
}

Expand Down Expand Up @@ -1247,7 +1259,7 @@ bool Item::hasMarketAttributes() const
}
} else if (attr.type == ITEM_ATTRIBUTE_DURATION) {
uint32_t duration = static_cast<uint32_t>(attr.value.integer);
if (duration != getDefaultDuration()) {
if (duration <= getDefaultDurationMin()) {
return false;
}
} else {
Expand Down
26 changes: 14 additions & 12 deletions src/item.h
Original file line number Diff line number Diff line change
Expand Up @@ -687,12 +687,19 @@ class Item : virtual public Thing
return static_cast<ItemDecayState_t>(getIntAttr(ITEM_ATTRIBUTE_DECAYSTATE));
}

int32_t getDecayTime() const
int32_t getDecayTimeMin() const
{
if (hasAttribute(ITEM_ATTRIBUTE_DURATION)) {
return getIntAttr(ITEM_ATTRIBUTE_DURATION);
if (hasAttribute(ITEM_ATTRIBUTE_DURATION_MIN)) {
return getIntAttr(ITEM_ATTRIBUTE_DURATION_MIN);
}
return items[id].decayTime;
return items[id].decayTimeMin;
}
int32_t getDecayTimeMax() const
{
if (hasAttribute(ITEM_ATTRIBUTE_DURATION_MAX)) {
return getIntAttr(ITEM_ATTRIBUTE_DURATION_MAX);
}
return items[id].decayTimeMax;
}

void setDecayTo(int32_t decayTo) { setIntAttr(ITEM_ATTRIBUTE_DECAYTO, decayTo); }
Expand Down Expand Up @@ -868,14 +875,9 @@ class Item : virtual public Thing

void setUniqueId(uint16_t n);

void setDefaultDuration()
{
uint32_t duration = getDefaultDuration();
if (duration != 0) {
setDuration(duration);
}
}
uint32_t getDefaultDuration() const { return items[id].decayTime * 1000; }
void setDefaultDuration();
uint32_t getDefaultDurationMin() const { return items[id].decayTimeMin * 1000; }
uint32_t getDefaultDurationMax() const { return items[id].decayTimeMax * 1000; }
bool canDecay() const;

virtual bool canRemove() const { return true; }
Expand Down
17 changes: 15 additions & 2 deletions src/items.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -661,8 +661,17 @@ void Items::parseItemNode(const pugi::xml_node& itemNode, uint16_t id)
}

pugi::xml_attribute valueAttribute = attributeNode.attribute("value");
pugi::xml_attribute maxValueAttr;
if (!valueAttribute) {
continue;
valueAttribute = attributeNode.attribute("minvalue");
if (!valueAttribute) {
continue;
}

maxValueAttr = attributeNode.attribute("maxvalue");
if (!maxValueAttr) {
continue;
}
}

std::string tmpStrValue = boost::algorithm::to_lower_copy<std::string>(keyAttribute.as_string());
Expand Down Expand Up @@ -931,7 +940,11 @@ void Items::parseItemNode(const pugi::xml_node& itemNode, uint16_t id)
}

case ITEM_PARSE_DURATION: {
it.decayTime = pugi::cast<uint32_t>(valueAttribute.value());
it.decayTimeMin = pugi::cast<uint32_t>(valueAttribute.value());

if (maxValueAttr) {
it.decayTimeMax = pugi::cast<uint32_t>(maxValueAttr.value());
}
break;
}

Expand Down
3 changes: 2 additions & 1 deletion src/items.h
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,8 @@ class ItemType
uint32_t attackSpeed = 0;
uint32_t weight = 0;
uint32_t levelDoor = 0;
uint32_t decayTime = 0;
uint32_t decayTimeMin = 0;
uint32_t decayTimeMax = 0;
uint32_t wieldInfo = 0;
uint32_t minReqLevel = 0;
uint32_t minReqMagicLevel = 0;
Expand Down
31 changes: 26 additions & 5 deletions src/luascript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1664,6 +1664,8 @@ void LuaScriptInterface::registerFunctions()
registerEnum(ITEM_ATTRIBUTE_STOREITEM);
registerEnum(ITEM_ATTRIBUTE_ATTACK_SPEED);
registerEnum(ITEM_ATTRIBUTE_OPENCONTAINER);
registerEnum(ITEM_ATTRIBUTE_DURATION_MIN);
registerEnum(ITEM_ATTRIBUTE_DURATION_MAX);

registerEnum(ITEM_TYPE_DEPOT);
registerEnum(ITEM_TYPE_MAILBOX);
Expand Down Expand Up @@ -3004,7 +3006,8 @@ void LuaScriptInterface::registerFunctions()
registerMethod("ItemType", "hasShowDuration", LuaScriptInterface::luaItemTypeHasShowDuration);
registerMethod("ItemType", "hasAllowDistRead", LuaScriptInterface::luaItemTypeHasAllowDistRead);
registerMethod("ItemType", "getWieldInfo", LuaScriptInterface::luaItemTypeGetWieldInfo);
registerMethod("ItemType", "getDuration", LuaScriptInterface::luaItemTypeGetDuration);
registerMethod("ItemType", "getDurationMin", LuaScriptInterface::luaItemTypeGetDurationMin);
registerMethod("ItemType", "getDurationMax", LuaScriptInterface::luaItemTypeGetDurationMax);
registerMethod("ItemType", "getLevelDoor", LuaScriptInterface::luaItemTypeGetLevelDoor);
registerMethod("ItemType", "getRuneSpellName", LuaScriptInterface::luaItemTypeGetRuneSpellName);
registerMethod("ItemType", "getVocationString", LuaScriptInterface::luaItemTypeGetVocationString);
Expand Down Expand Up @@ -13332,12 +13335,24 @@ int LuaScriptInterface::luaItemTypeGetWieldInfo(lua_State* L)
return 1;
}

int LuaScriptInterface::luaItemTypeGetDuration(lua_State* L)
int LuaScriptInterface::luaItemTypeGetDurationMin(lua_State* L)
{
// itemType:getDuration()
// itemType:getDurationMin()
const ItemType* itemType = getUserdata<const ItemType>(L, 1);
if (itemType) {
lua_pushinteger(L, itemType->decayTime);
lua_pushinteger(L, itemType->decayTimeMin);
} else {
lua_pushnil(L);
}
return 1;
}

int LuaScriptInterface::luaItemTypeGetDurationMax(lua_State* L)
{
// itemType:getDurationMax()
const ItemType* itemType = getUserdata<const ItemType>(L, 1);
if (itemType) {
lua_pushinteger(L, itemType->decayTimeMax);
} else {
lua_pushnil(L);
}
Expand Down Expand Up @@ -18043,7 +18058,13 @@ int LuaScriptInterface::luaWeaponDuration(lua_State* L)
uint16_t id = weapon->getID();
ItemType& it = Item::items.getItemType(id);

it.decayTime = getNumber<uint32_t>(L, 2);
if (isTable(L, 2)) {
it.decayTimeMin = getField<uint32_t>(L, 2, "min");
it.decayTimeMax = getField<uint32_t>(L, 2, "max");
} else {
it.decayTimeMin = getNumber<uint32_t>(L, 2);
}

it.showDuration = showDuration;
pushBoolean(L, true);
} else {
Expand Down
3 changes: 2 additions & 1 deletion src/luascript.h
Original file line number Diff line number Diff line change
Expand Up @@ -1259,7 +1259,8 @@ class LuaScriptInterface
static int luaItemTypeHasShowDuration(lua_State* L);
static int luaItemTypeHasAllowDistRead(lua_State* L);
static int luaItemTypeGetWieldInfo(lua_State* L);
static int luaItemTypeGetDuration(lua_State* L);
static int luaItemTypeGetDurationMin(lua_State* L);
static int luaItemTypeGetDurationMax(lua_State* L);
static int luaItemTypeGetLevelDoor(lua_State* L);
static int luaItemTypeGetRuneSpellName(lua_State* L);
static int luaItemTypeGetVocationString(lua_State* L);
Expand Down
2 changes: 1 addition & 1 deletion src/networkmessage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ void NetworkMessage::addItem(uint16_t id, uint8_t count)
add<uint32_t>(it.charges);
addByte(0x00); // boolean (is brand new)
} else if (it.showClientDuration) {
add<uint32_t>(it.decayTime);
add<uint32_t>(it.decayTimeMin);
addByte(0x00); // boolean (is brand new)
}

Expand Down

1 comment on commit a4ba6bf

@Coldensjo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MillhioreBT If you don't have minvalue and maxvalue on every single item with duration it will give you a completely random time.
So for example
<attribute key="duration" value="1800"/>
Would be
1 to 1800 seconds.

Please sign in to comment.