Updated npcspeed, npcwalkto and npcstop script commands (#8354)

* Added the optional parameter <npc name> to npcspeed to change the walking speed of the npc with the said name.
  Usage : npcspeed( <speed value> {,"<npc name>"} );

* Added the optional parameter <npc name> to npcwalkto to move the npc with the said name at the given coordinates.
  Usage : npcwalkto( <x>,<y> {,"<npc name>"} } );

* Added the optional parameters `<npc name>` and `<flag>` to `npcstop` to stop the movement of the npc with the said name with options.
  Usage : `npcstop( {"<npc name>", {"<flag>"}});`

Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
Co-authored-by: Aleos <aleos89@users.noreply.github.com>
This commit is contained in:
Atemo 2024-06-16 14:57:59 +02:00 committed by GitHub
parent fcf74b0dfc
commit 6451925430
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 128 additions and 45 deletions

View File

@ -7962,17 +7962,15 @@ Return values:
//
---------------------------------------
*npcspeed <speed value>;
*npcwalkto <x>,<y>;
*npcstop;
*npcspeed( <speed value> {,"<npc name>"} );
*npcwalkto( <x>,<y> {,"<npc name>"} } );
*npcstop( {"<npc name>", {"<flag>"}});
These commands will make the NPC object in question move around the map. As they
currently are, they are a bit buggy and are not useful for much more than making
an NPC move randomly around the map.
These commands will make the NPC object in question move around the map.
'npcspeed' will set the NPCs walking speed to a specified value. As in the
@speed GM command, 200 is the slowest possible speed while 0 is the fastest
possible (instant motion). 100 is the default character walking speed.
'npcspeed' will permanently set the NPCs walking speed to a specified value. As in the
@speed GM command, MAX_WALK_SPEED (1000) is the slowest possible speed while MIN_WALK_SPEED (20) is the fastest
possible (instant motion). DEFAULT_NPC_WALK_SPEED (200) is the default NPC walking speed.
'npcwalkto' will start the NPC sprite moving towards the specified coordinates
on the same map it is currently on. The script proceeds immediately after the
@ -7980,10 +7978,17 @@ NPC begins moving.
'npcstop' will stop the motion.
The <flag> value in npcstop affects how the unit is stopped. The following flags are bitwise values (can be combined using the pipe operator):
USW_NONE = Unit will keep walking to their original destination.
USW_FIXPOS = Issue a fixpos packet afterwards.
USW_MOVE_ONCE = Force the unit to move one cell if it hasn't yet.
USW_MOVE_FULL_CELL = Enable moving to the next cell when unit was already half-way there (may cause on-touch/place side-effects, such as a scripted map change).
USW_FORCE_STOP = Force stop moving.
Default: USW_FIXPOS | USW_MOVE_FULL_CELL | USW_FORCE_STOP
While in transit, the NPC will be clickable, but invoking it will cause it to
stop moving, which will make its coordinates different from what the client
computed based on the speed and motion coordinates. The effect is rather
unnerving.
computed based on the speed and motion coordinates.
Only a few NPC sprites have walking animations, and those that do, do not get
the animation invoked when moving the NPC, due to the problem in the NPC walking

View File

@ -90,7 +90,8 @@ typedef uint32 t_itemid;
#define MAX_FAME 1000000000 ///Max fame points
#define MAX_CART 100 ///Maximum item in cart
#define MAX_SKILL 1623 ///Maximum skill can be hold by Player, Homunculus, & Mercenary (skill list) AND skill_db limit
#define DEFAULT_WALK_SPEED 150 ///Default walk speed
#define DEFAULT_WALK_SPEED 150 ///Default walk speed (other than NPC)
#define DEFAULT_NPC_WALK_SPEED 200 ///Default NPC walk speed
#define MIN_WALK_SPEED 20 ///Min walk speed
#define MAX_WALK_SPEED 1000 ///Max walk speed
#define MAX_STORAGE 600 ///Max number of storage slots a player can have

View File

@ -204,7 +204,7 @@ void mvptomb_create(struct mob_data *md, char *killer, time_t time)
safestrncpy(nd->name, msg_txt(nullptr,656), sizeof(nd->name));
nd->class_ = 565;
nd->speed = 200;
nd->speed = DEFAULT_NPC_WALK_SPEED;
nd->subtype = NPCTYPE_TOMB;
nd->u.tomb.md = md;

View File

@ -776,7 +776,7 @@ void BarterDatabase::loadingFinished(){
npc_parsename( nd, barter->name.c_str(), nullptr, nullptr, __FILE__ ":" QUOTE(__LINE__) );
nd->class_ = barter->sprite;
nd->speed = 200;
nd->speed = DEFAULT_NPC_WALK_SPEED;
nd->bl.type = BL_NPC;
nd->subtype = NPCTYPE_BARTER;
@ -3820,7 +3820,7 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short
nd->class_ = JT_GUILD_FLAG;
else
nd->class_ = JT_WARPNPC;
nd->speed = 200;
nd->speed = DEFAULT_NPC_WALK_SPEED;
nd->u.warp.mapindex = to_mapindex;
nd->u.warp.x = to_x;
@ -3892,7 +3892,7 @@ static const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const
nd->class_ = JT_WARPNPC;
else
nd->class_ = JT_GUILD_FLAG;
nd->speed = 200;
nd->speed = DEFAULT_NPC_WALK_SPEED;
nd->u.warp.mapindex = i;
nd->u.warp.x = to_x;
@ -4176,7 +4176,7 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
npc_parsename(nd, w3, start, buffer, filepath);
nd->class_ = m == -1 ? JT_FAKENPC : npc_parseview(w4, start, buffer, filepath);
nd->speed = 200;
nd->speed = DEFAULT_NPC_WALK_SPEED;
++npc_shop;
nd->bl.type = BL_NPC;
@ -4414,7 +4414,7 @@ static const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, cons
npc_parsename(nd, w3, start, buffer, filepath);
nd->class_ = m == -1 ? JT_FAKENPC : npc_parseview(w4, start, buffer, filepath);
nd->speed = 200;
nd->speed = DEFAULT_NPC_WALK_SPEED;
nd->u.scr.script = script;
nd->u.scr.label_list = label_list;
nd->u.scr.label_list_num = label_list_num;
@ -4553,7 +4553,7 @@ const char* npc_parse_duplicate( char* w1, char* w2, char* w3, char* w4, const c
nd = npc_create_npc(m, x, y);
npc_parsename(nd, w3, start, buffer, filepath);
nd->class_ = m == -1 ? JT_FAKENPC : npc_parseview(w4, start, buffer, filepath);
nd->speed = 200;
nd->speed = DEFAULT_NPC_WALK_SPEED;
nd->src_id = src_id;
nd->bl.type = BL_NPC;
nd->subtype = (enum npc_subtype)type;
@ -4686,7 +4686,7 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) {
safestrncpy(wnd->name, "", ARRAYLENGTH(wnd->name));
safestrncpy(wnd->exname, newname, ARRAYLENGTH(wnd->exname));
wnd->class_ = JT_WARPNPC;
wnd->speed = 200;
wnd->speed = DEFAULT_NPC_WALK_SPEED;
wnd->u.warp.mapindex = map_id2index(imap);
wnd->u.warp.x = snd->u.warp.x;
wnd->u.warp.y = snd->u.warp.y;
@ -6236,7 +6236,7 @@ void do_init_npc(void){
// Init dummy NPC
fake_nd = npc_create_npc( -1, 0, 0 );
fake_nd->class_ = JT_FAKENPC;
fake_nd->speed = 200;
fake_nd->speed = DEFAULT_NPC_WALK_SPEED;
strcpy(fake_nd->name,"FAKE_NPC");
memcpy(fake_nd->exname, fake_nd->name, 9);

View File

@ -16071,48 +16071,120 @@ BUILDIN_FUNC(chatmes)
return SCRIPT_CMD_SUCCESS;
}
// change npc walkspeed [Valaris]
/**
* Change npc walkspeed.
* npcspeed <speed value> {,"<npc name>"};
*/
BUILDIN_FUNC(npcspeed)
{
struct npc_data* nd;
int speed;
npc_data* nd;
speed = script_getnum(st,2);
nd =(struct npc_data *)map_id2bl(st->oid);
if (script_hasdata(st, 3))
nd = npc_name2id(script_getstr(st, 3));
else
nd = map_id2nd(st->oid);
if( nd ) {
nd->speed = speed;
if (nd == nullptr) {
if (script_hasdata(st, 3))
ShowError("buildin_npcspeed: %s is a non-existing NPC.\n", script_getstr(st, 3));
else
ShowError("buildin_npcspeed: non-existing NPC.\n");
return SCRIPT_CMD_FAILURE;
}
int speed = script_getnum(st, 2);
if (speed < MIN_WALK_SPEED || speed > MAX_WALK_SPEED) {
ShowError("buildin_npcspeed: invalid speed %d (min: %d, max: %d).\n", speed, MIN_WALK_SPEED, MAX_WALK_SPEED);
return SCRIPT_CMD_FAILURE;
}
nd->speed = speed;
return SCRIPT_CMD_SUCCESS;
}
// make an npc walk to a position [Valaris]
/**
* Make an npc walk to a position.
* npcwalkto <x>,<y> {,"<npc name>"} };
*/
BUILDIN_FUNC(npcwalkto)
{
struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid);
int x=0,y=0;
npc_data* nd;
x=script_getnum(st,2);
y=script_getnum(st,3);
if (script_hasdata(st, 4))
nd = npc_name2id(script_getstr(st, 4));
else
nd = map_id2nd(st->oid);
if(nd) {
if (!nd->status.hp)
status_calc_npc(nd, SCO_FIRST);
if (nd == nullptr) {
if (script_hasdata(st, 4))
ShowError("buildin_npcwalkto: %s is a non-existing NPC.\n", script_getstr(st, 4));
else
status_calc_npc(nd, SCO_NONE);
unit_walktoxy(&nd->bl,x,y,0);
ShowError("buildin_npcwalkto: non-existing NPC.\n");
return SCRIPT_CMD_FAILURE;
}
if( nd->bl.m < 0 ){
ShowError( "buildin_npcwalkto: NPC is not on a map.\n" );
return SCRIPT_CMD_FAILURE;
}
struct map_data* mapdata = map_getmapdata( nd->bl.m );
int x = script_getnum(st, 2);
int y = script_getnum(st, 3);
if( x < 0 || x >= mapdata->xs || y < 0 || y >= mapdata->ys ){
ShowWarning( "buildin_npcwalkto: coordinates %d/%d are out of bounds in map %s(%dx%d).\n", x, y, mapdata->name, mapdata->xs, mapdata->ys );
return SCRIPT_CMD_FAILURE;
}
if (!nd->status.hp)
status_calc_npc(nd, SCO_FIRST);
else
status_calc_npc(nd, SCO_NONE);
unit_walktoxy(&nd->bl,x,y,0);
return SCRIPT_CMD_SUCCESS;
}
// stop an npc's movement [Valaris]
/**
* Stop an npc's movement.
* npcstop {"<npc name>", {"<flag>"}};
*/
BUILDIN_FUNC(npcstop)
{
struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid);
npc_data* nd;
if(nd) {
unit_stop_walking(&nd->bl,1|4);
if (script_hasdata(st, 2))
nd = npc_name2id(script_getstr(st, 2));
else
nd = map_id2nd(st->oid);
if (nd == nullptr) {
if (script_hasdata(st, 2))
ShowError("buildin_npcstop: %s is a non-existing NPC.\n", script_getstr(st, 2));
else
ShowError("buildin_npcstop: non-existing NPC.\n");
return SCRIPT_CMD_FAILURE;
}
int flag = USW_FIXPOS | USW_MOVE_FULL_CELL | USW_FORCE_STOP;
if (script_hasdata(st, 3)) {
flag = script_getnum(st, 3);
if (flag < USW_NONE || flag > USW_ALL) {
ShowError("buildin_npcstop: invalid flag %d.\n", flag);
return SCRIPT_CMD_FAILURE;
}
if (flag & USW_FORCE_STOP)
nd->ud.state.force_walk = false;
}
unit_stop_walking( &nd->bl, flag );
return SCRIPT_CMD_SUCCESS;
}
@ -27607,9 +27679,9 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(mobcount,"ss"),
BUILDIN_DEF(getlook,"i?"),
BUILDIN_DEF(getsavepoint,"i?"),
BUILDIN_DEF(npcspeed,"i"), // [Valaris]
BUILDIN_DEF(npcwalkto,"ii"), // [Valaris]
BUILDIN_DEF(npcstop,""), // [Valaris]
BUILDIN_DEF(npcspeed,"i?"),
BUILDIN_DEF(npcwalkto,"ii?"),
BUILDIN_DEF(npcstop,"??"),
BUILDIN_DEF(getmapxy,"rrr??"), //by Lorky [Lupus]
BUILDIN_DEF(mapid2name,"i"),
BUILDIN_DEF(checkoption1,"i?"),

View File

@ -10639,6 +10639,11 @@
export_constant(IWA_NONE);
export_constant(IWA_NOTDEAD);
/* npcspeed command */
export_constant(MIN_WALK_SPEED);
export_constant(MAX_WALK_SPEED);
export_constant(DEFAULT_NPC_WALK_SPEED);
/* skill hit */
export_constant(DMG_SINGLE);
export_constant(DMG_MULTI_HIT);