Age | Commit message (Collapse) | Author | Files | Lines |
|
Note: untested, but it now looks prettier and more correct >:)
Note2: it's not used anywhere in serverdata.
Approved-by: Thorbjørn Lindeijer <bjorn@lindeijer.nl>
|
|
Note: there were some checks before mob.cpp:3743 that I think applied on empty memory? Plus I moved the std::move right at the end of that loop. I'm not too familiar with move mechanics but it seems to work. YMMV.
Approved-by: Thorbjørn Lindeijer <bjorn@lindeijer.nl>
|
|
(see nullpo_retz(md) at start of function, plus md is used all over)
grep -r 'if.*[ (]md ' src
|
|
|
|
split, etc)
Rationale:
OnMobKillEvent invoked under PLAYER's RID - so using e.g. POS_X and
POS_Y returns PLAYER's coordinates when kill occured. The only extra data
available been @mobID - giving killed mob's type (class).
However, to "split" slimes I need to spawn few new mobs right on location
where kill occured - or some area around this spot, not player's X/Y.
This commit exposes 2 new variables set by server, @mob_X and @mob_Y
containing mob's X and Y coordinates when kill happened.
This is server-code change needed by relevant scripts.
Scripts itself would be landed a bit later to serverdata.
|
|
Build system overhaul: attoconf from python 2->3, add CMake
Merge request !280
|
|
In addition to item name.
Alternative to https://git.themanaworld.org/legacy/serverdata/-/merge_requests/808
|
|
This tag should reside within <head> tag. Placing it before head
seems to de-facto work, but technically appears to be bug.
Reported-by: lilly
****
|
|
|
|
|
|
|
|
|
|
|
|
|
|
as it was not possible to store a string variable with the current
format of the athena.txt I though a hash could help to identify the maps
since this one can be stored as a permanent char bound variable in
athena.txt
|
|
Try to be even more helpful, since configuration can vary.
|
|
This prints out the filename and what it tried to do, rather than raising
SIGABRT and silently dumping a core.
|
|
|
|
****
Approved-by: Free Yorp <thefreeyorp+git@gmail.com>
Approved-by: Thorbjørn Lindeijer <bjorn@lindeijer.nl>
Reviewed-by: Thorbjørn Lindeijer <bjorn@lindeijer.nl>
|
|
Also, just require the use of full paths when #including a generated file.
This fixes fresh out-of-tree builds using attoconf, and gets rid of a lot of
annoying terminal output when attoconf is tracing dependencies.
|
|
This should be reverted once we drop support for Ubuntu 18.04, and therefore
python3.6, as it does clutter up the code a bit.
Sourced from specing's work on the porting process.
See https://git.themanaworld.org/legacy/tmwa/-/merge_requests/256
|
|
Or more specifically, in the attoconf buildchain. attoconf itself directly
generates src/conf/install.hpp alongside Makefile, but version inforation
is only available later.
To generate version.hpp, I extended version.mk slightly to provide the recipe.
It's not anywhere near as generic as real.make tends to be, but with any luck
we'll soon be doing all builds through cmake going forward.
The template for install.hpp has been changed to use variables actually
provided by attoconf. PACKAGE{SYSCONF,LOCALSTATE}DIR are actually only defined
in real.make, and then only in terms of SYSCONFDIR and LOCALSTATEDIR, adding
`/tmwa`. It's simpler to just use the attoconf variable and adjust the
template, which conveniently also simplifies the construction in
CMakeLists.txt, too.
|
|
Also remove {install,version}.hpp from source control, so they're actually
generated.
There may be a better way to handle this, but I'll just leave a note as a
TODO for now.
|
|
The values of defines in these files should be the same as those set
from version.mk / Makefile.in.
|
|
This commit lands fix for infamous AFK-kill summons exploit.
Its what essentially caused summoner spells in cities to be disabled.
This is not free lunch: it comes at expense of little fun where
mob would bite bad master hitting it. But its been minor fun or
cosmetics while spells restriction in cities and so on is annoying
setback for mages.
So if choosing between evil and even more evil, guess...
Technically, server's bug is: it too eager to reattach some things to
wrong RID or something like this. Its what causes aggroed mob to
lock on really wrong random targets and AFK-kill them.
|
|
|
|
|
|
efficient.
Credit to @Hello for figuring this out :)
|
|
|
|
Nice consistency there, past!Freeyorp.
|
|
`npc_scriptcont` now consistently returns 1 on failure, though in practice,
this return value was always ignored.
|
|
055-1 _nodes.txt will call `destroy;` from within OnInit, that is during an
iteration of the global `ev_db`. Previously, concurrent modification
invalidated this iteration, resulting in a crash.
This still nullifes `oid`, dequeues all timers, and effectively calls
`builtin_end`.
`npc_data::deletion_pending` is extended to include a third state.
In addition to no deletion happening, and indicating when `npc_free` is
currently on the stack, it now also tracks whether the NPC is about to be
deleted by a timer.
This means that an NPC which is about to be deleted is still blocked from
triggering new events, much like an NPC actively being deleted would.
Starting or continuing an NPC dialog with an NPC that does not, or is about to
no longer exist, is now also blocked.
|
|
|
|
This is some rather impressive type safety, albeit safety that has evidently
desensitized people to warnings for rather serious problems.
|
|
PR !270 is an ongoing investigation into outstanding compiler warnings.
One such warning is `warning: format '%s' expects a matching 'char*' argument`
from `script_nullpo_end(nd, STRPRINTF("no such npc: '%s'"_fmt, name));` in
`src/map/script-fun.cpp`. No such warning is emitted from a similar line in
`src/map/atcommand.cpp`: `AString output = STRPRINTF("Jump to %s"_fmt, npc);`.
`script_nullpo_end` is a macro, rather than a function. `error` is passed in
verbatim by the preprocessor. The macro definition of `script_nullpo_end`
includes lines such as the following:
```cpp
PRINTF("script:%s: " #error " @ %s\n"_fmt, BUILTIN_NAME(), nullpo_nd->name);
```
`#<variable>` instructs the preprocessor to transform `<variable>` into a
literal string. In this case, the string literal:
```cpp
"STRPRINTF(\"no such npc: '%s'\"_fmt, name)"
```
So the entire line partly resolves to something like:
```cpp
printf("script:%s: STRPRINTF(\"no such npc: '%s'\"_fmt, name) @ %s\n"_fmt, BUILTIN_NAME(), nullpo_nd->name);
```
Once the compiler sees this, it throws out the warning seen here, because
printf is seeing three placeholders in the formatter, but is only given two
value arguments.
Checking with `gcc -E`, the full expansion is as follows:
```cpp
if (nullpo_chk("script-fun.cpp", 4885, __PRETTY_FUNCTION__, nd)) { if (st->oid) { dumb_ptr<npc_data> nullpo_nd = map_id_is_npc(st->oid); if (nullpo_nd && nullpo_nd->name) { ({ struct format_impl { constexpr static FormatString print_format() __asm__("_print_format") { return "script:%s: " "STRPRINTF(\"no such npc: '%s'\"_fmt, npc)" " @ %s\n"_fmt; } }; cxxstdio::PrintFormatter<format_impl>::print((
# 4885 "script-fun.cpp" 3 4
stdout
# 4885 "script-fun.cpp"
), (builtin_functions[st->stack->stack_datav[st->start].get_if<ScriptDataFuncRef>()->numi].name), nullpo_nd->name); }); } else if (nullpo_nd) { ({ struct format_impl { constexpr static FormatString print_format() __asm__("_print_format") { return "script:%s: " "STRPRINTF(\"no such npc: '%s'\"_fmt, npc)" " (unnamed npc)\n"_fmt; } }; cxxstdio::PrintFormatter<format_impl>::print((
# 4885 "script-fun.cpp" 3 4
stdout
# 4885 "script-fun.cpp"
), (builtin_functions[st->stack->stack_datav[st->start].get_if<ScriptDataFuncRef>()->numi].name)); }); } else { ({ struct format_impl { constexpr static FormatString print_format() __asm__("_print_format") { return "script:%s: " "STRPRINTF(\"no such npc: '%s'\"_fmt, npc)" " (no npc)\n"_fmt; } }; cxxstdio::PrintFormatter<format_impl>::print((
# 4885 "script-fun.cpp" 3 4
stdout
# 4885 "script-fun.cpp"
), (builtin_functions[st->stack->stack_datav[st->start].get_if<ScriptDataFuncRef>()->numi].name)); }); } } else { ({ struct format_impl { constexpr static FormatString print_format() __asm__("_print_format") { return "script:%s: " "STRPRINTF(\"no such npc: '%s'\"_fmt, npc)" " (no npc)\n"_fmt; } }; cxxstdio::PrintFormatter<format_impl>::print((
# 4885 "script-fun.cpp" 3 4
stdout
# 4885 "script-fun.cpp"
), (builtin_functions[st->stack->stack_datav[st->start].get_if<ScriptDataFuncRef>()->numi].name)); }); } st->state = ScriptEndState::END; return; };
```
Note the string literal: `"STRPRINTF(\"no such npc: '%s'\"_fmt, npc)"`.
`script_nullpo_end` currently can't take as its argument for `error` any
expression which, when stringified, contains something which `printf` will
interpret as its formatter expecting another argument.
This appears to have been broken since it was first introduced in
https://git.themanaworld.org/legacy/tmwa/-/commit/594eafd4f231a897cbefd
since the first revision implicitly had these requirements, and also
introduced usage which didn't meet them.
This rewrites each PRINTF line in `script_nullpo_end` from the template
```cpp
PRINTF("script:%s: " #error " @ %s\n"_fmt, BUILTIN_NAME(), nullpo_nd->name);
```
to something like
```cpp
PRINTF("script:%s: %s @ %s\n"_fmt, BUILTIN_NAME(), error, nullpo_nd->name);
```
This means that instead of an expression being stringified, error is
interpreted as an expression that resolves (or decays) to a string.
This seems consistent with all current usage of `script_nullpo_end`.
|
|
|
|
|
|
Squash with: remove empty lines
|
|
|
|
C++11 was a really long time ago, huh?
|
|
|
|
|
|
In serverdata@c3b7fe59a, `magic-knuckles` made use of temporary copies of the
spell NPC via `puppet`/`destroy` to provide additional functionality. This
implementation was correct with respect to tmwa behaviour as documented.
However, `puppet` and `destroy` doesn't quite return the server to a clean
prior state. In `builtin_puppet`, events with the fresh new copy of NPC are
registered into the global `ev_db` map to track named events, such as
`OnDischarge`, which might be triggered later. However, these registrations
are not reversed with `destroy`, leaving `ev_db` to retain references to now
invalid and destroyed NPCs.
serverdata@c3b7fe59a revealed this oversight through an intersection of rare
conditions:
- An NPC that is routinely cloned and destroyed
- Having a variety of events
- Including one that can be triggered during a search for the event over ALL
NPCs when `#discharge` is cast.
To reproduce, compile with `-fsanitize=address -fsanitize=undefined` to more
reliably catch use of invalid memory, cast `magic-knuckles`, log out the
character which cast `magic-knuckles` to destroy the NPC, log back in, then
cast `#discharge`. The server will then crash.
Special thanks to SystemError for testing out this theory. Currently lacking
a test environment of my own, this would not have been possible without his
patience and diligence.
|
|
Blame Ledmitz (:
|
|
|
|
Preserve @exprate as a shortcut for both & because scripts in serverdata call it
|
|
|
|
See "Item Mode" commit from Apr 3 2023
|
|
pt item when base stat is 1.
What is funnier is that it sent updates for all other 5 (unchanged
stats). Example, amethyst ring +1 dex:
Sending update for stat 0: saved: 0+1, new: 0+0 (str?)
Sending update for stat 1: saved: 0+1, new: 0+0 (agi?)
Sending update for stat 2: saved: 0+1, new: 0+0 (vit?)
Sending update for stat 3: saved: 0+1, new: 0+0 (int?)
Sending update for stat 5: saved: 0+1, new: 0+0 (luk?)
|
|
|