diff options
author | Smokexyz <sagunkho@hotmail.com> | 2017-02-22 18:26:14 +0800 |
---|---|---|
committer | Smokexyz <sagunkho@hotmail.com> | 2017-04-04 14:07:08 +0800 |
commit | a6ca899ac0aa2be7ce1c04beec847f3d3e703b01 (patch) | |
tree | c6e41844f490fc8a1100e2bef7ecebb4f4e38321 /src | |
parent | 20145c61053479b9acd8ed50c75a80c2a861e349 (diff) | |
download | hercules-a6ca899ac0aa2be7ce1c04beec847f3d3e703b01.tar.gz hercules-a6ca899ac0aa2be7ce1c04beec847f3d3e703b01.tar.bz2 hercules-a6ca899ac0aa2be7ce1c04beec847f3d3e703b01.tar.xz hercules-a6ca899ac0aa2be7ce1c04beec847f3d3e703b01.zip |
Implementation of unit controlling script commands.
Setunitdata <GID>, <DataType>, <Val1> {, <Val2>, <Val3>}
Getunitdata <GUID>, <DataType> {, <Variable>}
Getunitname <unit id>
Setunitname <unit id>, <name>
Performs alteration and retrieval of real-time unit data for a game object of the types -
NPCs, Pets, Monsters, Homunuculus', Mercenaries, Elementals.
Applicable data types (available as script constants) -
UDT_TYPE: Unit Type value (BL_MOB, BL_NPC, BL_PET, BL_ELEM, BL_MER, BL_HOM)
UDT_SIZE: Unit Size
UDT_LEVEL: Level
UDT_HP: Current HP
UDT_MAXHP: Max HP
UDT_SP: SP
UDT_MAXSP: MAX SP
UDT_MASTERAID: Master Account ID (for Summons)
UDT_MASTERCID: Master Char ID (for Summons)
UDT_MAPIDXY: Warp a Unit to a map.
UDT_WALKTOXY: Make a unit walk to certain co-ordinates.
UDT_SPEED: Unit Speed
UDT_MODE: Mode (Mobs)
UDT_AI: Unit AI Type
UDT_SCOPTION: Status Options.
UDT_SEX: mm Sex.
UDT_CLASS: Class of the unit.
UDT_HAIRSTYLE: Hair Style of the unit.
UDT_HAIRCOLOR: Hair Color.
UDT_HEADBOTTOM: Headgear Bottom Sprite.
UDT_HEADMIDDLE: Headgear Middle Sprite.
UDT_HEADTOP: Headegar Top Sprite.
UDT_CLOTHCOLOR: Cloth Color.
UDT_SHIELD: Shield Sprite.
UDT_WEAPON: Weapon Sprite.
UDT_LOOKDIR: Face direction.
UDT_CANMOVETICK:Stop a unit from move for n seconds.
UDT_STR: Unit STR.
UDT_AGI: Unit AGI.
UDT_VIT: Unit VIT.
UDT_INT: Unit INT.
UDT_DEX: Unit DEX.
UDT_LUK: Unit LUK.
UDT_ATKRANGE: Attack range of a unit.
UDT_ATKMIN: Min Atk of a unit.
UDT_ATKMAX: Max Atk of a unit.
UDT_MATKMIN: Min MATK of a unit.
UDT_MATKMAX: Max MATK of a unit.
UDT_DEF: DEF.
UDT_MDEF: MDEF.
UDT_HIT: HIT.
UDT_FLEE: FLEE.
UDT_PDODGE: Perfect Dodge.
UDT_CRIT: Critical Rate.
UDT_RACE: Race. (Eg. string constants RC_DemiHuman or Integer 7).
UDT_ELETYPE: Element. (Eg. string constants Ele_Neutral or Integer 0).
UDT_ELELEVEL: Element Level (int).
UDT_AMOTION: AMotion Rate (int).
UDT_ADELAY: ADelay Rate (int).
UDT_DMOTION: DMotion Rate (int).
UDT_HUNGER: Hunger Rate (int) - for summons.
UDT_INTIMACY: Intimacy Rate (int) - for summons.
UDT_LIFETIME: LifeTime (int) - for summons.
UDT_MERC_KILLCOUNT: Kill count for mercenaries (int).
UDT_STATPOINT: Status Points (int) - for npcs.
Addition of AI constants as well.
Documentation is included.
Credits: [rA](https://github.com/rathena/rathena/commit/2cee5b6ff1bf53c4ae53bc1278b09ae84b8a0a76) & [Smokexyz](https://github.com/Smokexyz)
Diffstat (limited to 'src')
-rw-r--r-- | src/map/script.c | 1600 | ||||
-rw-r--r-- | src/map/script.h | 75 |
2 files changed, 1675 insertions, 0 deletions
diff --git a/src/map/script.c b/src/map/script.c index 38931bd11..ceb16eb36 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -17084,6 +17084,1601 @@ BUILDIN(getunittype) { return true; } +/** + * Sets real-time unit data for a game object. + * Setunitdata <GUID>,<DataType>,<Val1>{,<Val2>,<Val3>} + * @param1 GUID GID of the unit. + * @param2 DataType Type of Data to be set for the unit. + * @param3 Value#1 Value to be passed as change in data. + * @param4 Value#2 Optional int value to be passed for certain data types. + * @param5 Value#3 Optional int value to be passed for certain data types. + * @return 1 on success, 0 on failure. + */ +BUILDIN(setunitdata) +{ + struct block_list *bl = NULL; + const char *mapname = NULL, *udtype = NULL; + int type = 0, val = 0, val2 = 0, val3 = 0; + struct map_session_data *tsd = NULL; + + bl = map->id2bl(script_getnum(st, 2)); + + if (bl == NULL) { + ShowWarning("buildin_setunitdata: Error in finding object with given GID %d!\n", script_getnum(st, 2)); + script_pushint(st, 0); + return false; + } + + type = script_getnum(st, 3); + + /* type bounds */ + if (type < UDT_SIZE || type >= UDT_MAX) { + ShowError("buildin_setunitdata: Invalid unit data type %d provided.\n", type); + script_pushint(st, 0); + return false; + } + + /* Mandatory Argument 3 */ + if (type == UDT_MAPIDXY) { + if (!script_isstringtype(st, 4)) { + ShowError("buildin_setunitdata: Invalid data type for argument #3.\n"); + script_pushint(st, 0); + return false; + } + mapname = script_getstr(st, 4); + } else { + if (script_isstringtype(st, 4)) { + ShowError("buildin_setunitdata: Invalid data type for argument #3.\n"); + script_pushint(st, 0); + return false; + } + val = script_getnum(st, 4); + } +/* checks if value is out of bounds. */ +#define setunitdata_check_bounds(arg, min, max) \ + do { \ + if (script_getnum(st, arg) < min || script_getnum(st, arg) > max) { \ + ShowError("buildin_setunitdata: Invalid value %d for argument #%d. (min: %d, max: %d)\n", script_getnum(st, arg), arg-1, min, max); \ + script_pushint(st, 0); \ + return false; \ + } \ + } while(0); +/* checks if value is out of bounds. */ +#define setunitdata_check_unsigned(arg, max) \ + do { \ + if (script_getnum(st, arg) < 0 || script_getnum(st, arg) > max) { \ + ShowError("buildin_setunitdata: Invalid value %d for argument #%d. (min: 0, max: %u)\n", script_getnum(st, arg), arg-1, max); \ + script_pushint(st, 0); \ + return false; \ + } \ + } while(0); +/* checks if uint64 value is out of bounds. */ +#define setunitdata_check_uint64(arg, min, max) \ + do { \ + if (script_getnum(st, arg) < min || script_getnum(st, arg) > max) { \ + ShowError("buildin_setunitdata: Invalid value %d for argument #%d. (min: %d, max: %"PRIu64")\n", script_getnum(st, arg), arg-1, min, max); \ + script_pushint(st, 0); \ + return false; \ + } \ + } while(0); +/* checks if the argument doesn't exist, if required. + * also checks if the argument exists, if not required. */ +#define setunitdata_assert_arg(arg, required) \ + do { \ + if (required && !script_hasdata(st, arg)) { \ + ShowError("buildin_setunitdata: Type %d reqires argument #%d.\n", type, arg-1); \ + script_pushint(st, 0); \ + return false; \ + } else if (!required && script_hasdata(st, arg)) { \ + ShowError("buildin_setunitdata: Argument %d is not required for type %d.\n", arg-1, type); \ + script_pushint(st, 0); \ + return false; \ + } \ + } while (0); +/* checks if the data is an integer. */ +#define setunitdata_check_int(arg) \ + do { \ + setunitdata_assert_arg(arg, true); \ + if (script_isstringtype(st, arg)) { \ + ShowError("buildin_setunitdata: Argument #%d expects integer, string given.\n", arg-1); \ + script_pushint(st, 0); \ + return false; \ + } \ + } while(0); +/* checks if the data is a string. */ +#define setunitdata_check_string(arg) \ + do { \ + setunitdata_assert_arg(arg, true); \ + if (script_isinttype(st, arg)) { \ + ShowError("buildin_setunitdata: Argument #%d expects string, integer given.\n", arg-1); \ + script_pushint(st, 0); \ + return false; \ + } \ + } while(0); + + if (type != UDT_MAPIDXY && type != UDT_WALKTOXY) { + setunitdata_assert_arg(5, false); + setunitdata_assert_arg(6, false); + } + + switch (type) + { + case UDT_SIZE: + setunitdata_check_bounds(4, SZ_SMALL, SZ_BIG); + break; + case UDT_LEVEL: + case UDT_HP: + case UDT_MAXHP: + case UDT_SP: + case UDT_MAXSP: + case UDT_CLASS: + case UDT_HEADBOTTOM: + case UDT_HEADMIDDLE: + case UDT_HEADTOP: + case UDT_CLOTHCOLOR: + case UDT_SHIELD: + case UDT_WEAPON: + case UDT_INTIMACY: + case UDT_LIFETIME: + case UDT_MERC_KILLCOUNT: + setunitdata_check_unsigned(4, UINT_MAX); + break; + case UDT_MASTERAID: + setunitdata_check_unsigned(4, UINT_MAX); + tsd = map->id2sd(val); + if (tsd == NULL) { + ShowWarning("buildin_setunitdata: Account ID %d not found for master change!\n",val); + script_pushint(st, 0); + return false; + } + break; + case UDT_MASTERCID: + setunitdata_check_unsigned(4, UINT_MAX); + tsd = map->charid2sd((uint32) val); + if (tsd == NULL) { + ShowWarning("buildin_setunitdata: Character ID %d not found for master change!\n",val); + script_pushint(st, 0); + return false; + } + break; + case UDT_MAPIDXY: + if ((val = map->mapname2mapid(mapname)) == -1) { + ShowError("buildin_setunitdata: Non-existent map %s provided.\n", mapname); + return false; + } + setunitdata_check_int(5); + setunitdata_check_int(6); + setunitdata_check_bounds(5, 0, MAX_MAP_SIZE/2); + setunitdata_check_bounds(6, 0, MAX_MAP_SIZE/2); + val2 = script_getnum(st, 5); + val3 = script_getnum(st, 6); + break; + case UDT_WALKTOXY: + setunitdata_assert_arg(6, false); + setunitdata_check_int(5); + val2 = script_getnum(st, 5); + setunitdata_check_bounds(4, 0, MAX_MAP_SIZE/2); + setunitdata_check_bounds(5, 0, MAX_MAP_SIZE/2); + break; + case UDT_SPEED: + setunitdata_check_bounds(4, 0, MAX_WALK_SPEED); + break; + case UDT_MODE: + setunitdata_check_bounds(4, MD_NONE, MD_MASK); + break; + case UDT_AI: + setunitdata_check_bounds(4, AI_NONE, AI_MAX-1); + break; + case UDT_SCOPTION: + setunitdata_check_bounds(4, OPTION_NOTHING, OPTION_COSTUME); + break; + case UDT_SEX: + setunitdata_check_bounds(4, SEX_FEMALE, SEX_MALE); + break; + case UDT_HAIRSTYLE: + setunitdata_check_bounds(4, 0, battle->bc->max_hair_style); + break; + case UDT_HAIRCOLOR: + setunitdata_check_bounds(4, 0, battle->bc->max_hair_color); + break; + case UDT_LOOKDIR: + setunitdata_check_bounds(4, 0, 7); + break; + case UDT_CANMOVETICK: + setunitdata_check_uint64(4, 0, UINT64_MAX); + break; + case UDT_STR: + case UDT_AGI: + case UDT_VIT: + case UDT_INT: + case UDT_DEX: + case UDT_LUK: + case UDT_STATPOINT: + case UDT_ATKRANGE: + case UDT_ATKMIN: + case UDT_ATKMAX: + case UDT_MATKMIN: + case UDT_MATKMAX: + case UDT_AMOTION: + case UDT_ADELAY: + case UDT_DMOTION: + setunitdata_check_bounds(4, 0, USHRT_MAX); + break; + case UDT_DEF: + case UDT_MDEF: + case UDT_HIT: + case UDT_FLEE: + case UDT_PDODGE: + case UDT_CRIT: + setunitdata_check_bounds(4, 0, SHRT_MAX); + break; + case UDT_HUNGER: + setunitdata_check_bounds(4, 0, 99); + break; + case UDT_RACE: + case UDT_ELETYPE: + case UDT_ELELEVEL: + setunitdata_check_bounds(4, 0, CHAR_MAX); + break; + default: + break; + } + +#undef setunitdata_check_bounds +#undef setunitdata_check_uint64 +#undef setunitdata_assert_arg +#undef setunitdata_check_int +#undef setunitdata_check_string + + /* Set the values */ + switch (bl->type) { + case BL_MOB: + { + struct mob_data *md = BL_UCAST(BL_MOB, bl); + nullpo_retr(false, md); + + switch (type) + { + case UDT_SIZE: + md->status.size = (unsigned char) val; + break; + case UDT_LEVEL: + md->level = val; + break; + case UDT_HP: + status->set_hp(bl, (unsigned int) val, 0); + clif->charnameack(0, &md->bl); + break; + case UDT_MAXHP: + md->status.max_hp = (unsigned int) val; + clif->charnameack(0, &md->bl); + break; + case UDT_SP: + status->set_sp(bl, (unsigned int) val, 0); + break; + case UDT_MAXSP: + md->status.max_sp = (unsigned int) val; + break; + case UDT_MASTERAID: + md->master_id = val; + break; + case UDT_MAPIDXY: + unit->warp(bl, (short) val, (short) val2, (short) val3, CLR_TELEPORT); + break; + case UDT_WALKTOXY: + if (!unit->walktoxy(bl, (short) val, (short) val2, 2)) + unit->movepos(bl, (short) val, (short) val2, 0, 0); + break; + case UDT_SPEED: + md->status.speed = (unsigned short) val; + status->calc_misc(bl, &md->status, md->level); + break; + case UDT_MODE: + md->status.mode = (enum e_mode) val; + break; + case UDT_AI: + md->special_state.ai = (enum ai) val; + break; + case UDT_SCOPTION: + md->sc.option = (char) val; + break; + case UDT_SEX: + md->vd->sex = (char) val; + break; + case UDT_CLASS: + mob->class_change(md, val); + break; + case UDT_HAIRSTYLE: + clif->changelook(bl, LOOK_HAIR, (unsigned short) val); + break; + case UDT_HAIRCOLOR: + clif->changelook(bl, LOOK_HAIR_COLOR, (unsigned short) val); + break; + case UDT_HEADBOTTOM: + clif->changelook(bl, LOOK_HEAD_BOTTOM, (unsigned short) val); + break; + case UDT_HEADMIDDLE: + clif->changelook(bl, LOOK_HEAD_MID, (unsigned short) val); + break; + case UDT_HEADTOP: + clif->changelook(bl, LOOK_HEAD_TOP, (unsigned short) val); + break; + case UDT_CLOTHCOLOR: + clif->changelook(bl, LOOK_CLOTHES_COLOR, (unsigned short) val); + break; + case UDT_SHIELD: + clif->changelook(bl, LOOK_SHIELD, (unsigned short) val); + break; + case UDT_WEAPON: + clif->changelook(bl, LOOK_WEAPON, (unsigned short) val); + break; + case UDT_LOOKDIR: + unit->setdir(bl, (uint8) val); + break; + case UDT_CANMOVETICK: + md->ud.canmove_tick = (int64) val; + break; + case UDT_STR: + md->status.str = (unsigned short) val; + status->calc_misc(bl, &md->status, md->level); + break; + case UDT_AGI: + md->status.agi = (unsigned short) val; + status->calc_misc(bl, &md->status, md->level); + break; + case UDT_VIT: + md->status.vit = (unsigned short) val; + status->calc_misc(bl, &md->status, md->level); + break; + case UDT_INT: + md->status.int_ = (unsigned short) val; + status->calc_misc(bl, &md->status, md->level); + break; + case UDT_DEX: + md->status.dex = (unsigned short) val; + status->calc_misc(bl, &md->status, md->level); + break; + case UDT_LUK: + md->status.luk = (unsigned short) val; + status->calc_misc(bl, &md->status, md->level); + break; + case UDT_ATKRANGE: + md->status.rhw.range = (unsigned short) val; + break; + case UDT_ATKMIN: + md->status.rhw.atk = (unsigned short) val; + break; + case UDT_ATKMAX: + md->status.rhw.atk2 = (unsigned short) val; + break; + case UDT_MATKMIN: + md->status.matk_min = (unsigned short) val; + break; + case UDT_MATKMAX: + md->status.matk_max = (unsigned short) val; + break; + case UDT_DEF: + md->status.def = (defType) val; + break; + case UDT_MDEF: + md->status.mdef = (defType) val; + break; + case UDT_HIT: + md->status.hit = (short) val; + break; + case UDT_FLEE: + md->status.flee = (short) val; + break; + case UDT_PDODGE: + md->status.flee2 = (short) val; + break; + case UDT_CRIT: + md->status.cri = (short) val; + break; + case UDT_RACE: + md->status.race = (unsigned char) val; + break; + case UDT_ELETYPE: + md->status.def_ele = (unsigned char) val; + break; + case UDT_ELELEVEL: + md->status.ele_lv = (unsigned char) val; + break; + case UDT_AMOTION: + md->status.amotion = (unsigned short) val; + break; + case UDT_ADELAY: + md->status.adelay = (unsigned short) val; + break; + case UDT_DMOTION: + md->status.dmotion = (unsigned short) val; + break; + default: + ShowWarning("buildin_setunitdata: Invalid data type '%s' for mob unit.\n", udtype); + script_pushint(st, 0); + return false; + } + } + break; + case BL_HOM: + { + struct homun_data *hd = BL_UCAST(BL_HOM, bl); + + nullpo_retr(false, hd); + + switch (type) + { + case UDT_SIZE: + hd->base_status.size = (unsigned char) val; + break; + case UDT_LEVEL: + hd->homunculus.level = (short) val; + break; + case UDT_HP: + status->set_hp(bl, (unsigned int) val, 0); + break; + case UDT_MAXHP: + hd->homunculus.max_hp = val; + break; + case UDT_SP: + status->set_sp(bl, (unsigned int) val, 0); + break; + case UDT_MAXSP: + hd->homunculus.max_sp = val; + break; + case UDT_MASTERCID: + hd->homunculus.char_id = val; + hd->master = tsd; + break; + case UDT_MAPIDXY: + unit->warp(bl, (short) val, (short) val2, (short) val3, CLR_TELEPORT); + break; + case UDT_WALKTOXY: + if (!unit->walktoxy(bl, (short) val, (short) val2, 2)) + unit->movepos(bl, (short) val, (short) val2, 0, 0); + break; + case UDT_SPEED: + hd->base_status.speed = (unsigned short) val; + status->calc_misc(bl, &hd->base_status, hd->homunculus.level); + break; + case UDT_LOOKDIR: + unit->setdir(bl, (unsigned char) val); + break; + case UDT_CANMOVETICK: + hd->ud.canmove_tick = (int64) val; + break; + case UDT_STR: + hd->base_status.str = (unsigned short) val; + status->calc_misc(bl, &hd->base_status, hd->homunculus.level); + break; + case UDT_AGI: + hd->base_status.agi = (unsigned short) val; + status->calc_misc(bl, &hd->base_status, hd->homunculus.level); + break; + case UDT_VIT: + hd->base_status.vit = (unsigned short) val; + status->calc_misc(bl, &hd->base_status, hd->homunculus.level); + break; + case UDT_INT: + hd->base_status.int_ = (unsigned short) val; + status->calc_misc(bl, &hd->base_status, hd->homunculus.level); + break; + case UDT_DEX: + hd->base_status.dex = (unsigned short) val; + status->calc_misc(bl, &hd->base_status, hd->homunculus.level); + break; + case UDT_LUK: + hd->base_status.luk = (unsigned short) val; + status->calc_misc(bl, &hd->base_status, hd->homunculus.level); + break; + case UDT_ATKRANGE: + hd->base_status.rhw.range = (unsigned short) val; + break; + case UDT_ATKMIN: + hd->base_status.rhw.atk = (unsigned short) val; + break; + case UDT_ATKMAX: + hd->base_status.rhw.atk2 = (unsigned short) val; + break; + case UDT_MATKMIN: + hd->base_status.matk_min = (unsigned short) val; + break; + case UDT_MATKMAX: + hd->base_status.matk_max = (unsigned short) val; + break; + case UDT_DEF: + hd->base_status.def = (defType) val; + break; + case UDT_MDEF: + hd->base_status.mdef = (defType) val; + break; + case UDT_HIT: + hd->base_status.hit = (short) val; + break; + case UDT_FLEE: + hd->base_status.flee = (short) val; + break; + case UDT_PDODGE: + hd->base_status.flee2 = (short) val; + break; + case UDT_CRIT: + hd->base_status.cri = (short) val; + break; + case UDT_RACE: + hd->base_status.race = (unsigned char) val; + break; + case UDT_ELETYPE: + hd->base_status.def_ele = (unsigned char) val; + break; + case UDT_ELELEVEL: + hd->base_status.ele_lv = (unsigned char) val; + break; + case UDT_AMOTION: + hd->base_status.amotion = (unsigned short) val; + break; + case UDT_ADELAY: + hd->base_status.adelay = (unsigned short) val; + break; + case UDT_DMOTION: + hd->base_status.dmotion = (unsigned short) val; + break; + case UDT_HUNGER: + hd->homunculus.hunger = (short) val; + clif->send_homdata(hd->master, SP_HUNGRY, hd->homunculus.hunger); + break; + case UDT_INTIMACY: + homun->add_intimacy(hd, (unsigned int) val); + clif->send_homdata(hd->master, SP_INTIMATE, hd->homunculus.intimacy / 100); + break; + default: + ShowWarning("buildin_setunitdata: Invalid data type '%s' for homunculus unit.\n", udtype); + script_pushint(st, 0); + return false; + } + + clif->send_homdata(hd->master, SP_ACK, 0); // send homun data + } + break; + case BL_PET: + { + struct pet_data *pd = BL_UCAST(BL_PET, bl); + + nullpo_retr(false, pd); + + switch (type) + { + case UDT_SIZE: + pd->status.size = (unsigned char) val; + break; + case UDT_LEVEL: + pd->pet.level = (short) val; + break; + case UDT_HP: + status->set_hp(bl, (unsigned int) val, 0); + break; + case UDT_MAXHP: + pd->status.max_hp = (unsigned int) val; + break; + case UDT_SP: + status->set_sp(bl, (unsigned int) val, 0); + break; + case UDT_MAXSP: + pd->status.max_sp = (unsigned int) val; + break; + case UDT_MASTERAID: + pd->pet.account_id = (int) val; + pd->msd = tsd; + break; + case UDT_MAPIDXY: + unit->warp(bl, (short) val, (short) val2, (short) val3, CLR_TELEPORT); + break; + case UDT_WALKTOXY: + if (!unit->walktoxy(bl, (short) val, (short) val2, 2)) + unit->movepos(bl, (short) val, (short) val2, 0, 0); + break; + case UDT_SPEED: + pd->status.speed = (unsigned short) val; + status->calc_misc(bl, &pd->status, pd->pet.level); + break; + case UDT_LOOKDIR: + unit->setdir(bl, (unsigned char) val); + break; + case UDT_CANMOVETICK: + pd->ud.canmove_tick = (int64) val; + break; + case UDT_STR: + pd->status.str = (unsigned short) val; + status->calc_misc(bl, &pd->status, pd->pet.level); + break; + case UDT_AGI: + pd->status.agi = (unsigned short) val; + status->calc_misc(bl, &pd->status, pd->pet.level); + break; + case UDT_VIT: + pd->status.vit = (unsigned short) val; + status->calc_misc(bl, &pd->status, pd->pet.level); + break; + case UDT_INT: + pd->status.int_ = (unsigned short) val; + status->calc_misc(bl, &pd->status, pd->pet.level); + break; + case UDT_DEX: + pd->status.dex = (unsigned short) val; + status->calc_misc(bl, &pd->status, pd->pet.level); + break; + case UDT_LUK: + pd->status.luk = (unsigned short) val; + status->calc_misc(bl, &pd->status, pd->pet.level); + break; + case UDT_ATKRANGE: + pd->status.rhw.range = (unsigned short) val; + break; + case UDT_ATKMIN: + pd->status.rhw.atk = (unsigned short) val; + break; + case UDT_ATKMAX: + pd->status.rhw.atk2 = (unsigned short) val; + break; + case UDT_MATKMIN: + pd->status.matk_min = (unsigned short) val; + break; + case UDT_MATKMAX: + pd->status.matk_max = (unsigned short) val; + break; + case UDT_DEF: + pd->status.def = (defType) val; + break; + case UDT_MDEF: + pd->status.mdef = (defType) val; + break; + case UDT_HIT: + pd->status.hit = (short) val; + break; + case UDT_FLEE: + pd->status.flee = (short) val; + break; + case UDT_PDODGE: + pd->status.flee2 = (short) val; + break; + case UDT_CRIT: + pd->status.cri = (short) val; + break; + case UDT_RACE: + pd->status.race = (unsigned char) val; + break; + case UDT_ELETYPE: + pd->status.def_ele = (unsigned char) val; + break; + case UDT_ELELEVEL: + pd->status.ele_lv = (unsigned char) val; + break; + case UDT_AMOTION: + pd->status.amotion = (unsigned short) val; + break; + case UDT_ADELAY: + pd->status.adelay = (unsigned short) val; + break; + case UDT_DMOTION: + pd->status.dmotion = (unsigned short) val; + break; + case UDT_INTIMACY: + pet->set_intimate(pd, val); + clif->send_petdata(pd->msd,pd,1,pd->pet.intimate); + break; + case UDT_HUNGER: pd->pet.hungry = (short) val; + break; + default: + ShowWarning("buildin_setunitdata: Invalid data type '%s' for pet unit.\n", udtype); + script_pushint(st, 0); + return false; + } + clif->send_petstatus(pd->msd); // send pet data + } + break; + case BL_MER: + { + struct mercenary_data *mc = BL_UCAST(BL_MER, bl); + + nullpo_retr(false, mc); + + switch (type) + { + case UDT_SIZE: + mc->base_status.size = (unsigned char) val; + break; + case UDT_HP: + status->set_hp(bl, (unsigned int) val, 0); + break; + case UDT_MAXHP: + mc->base_status.max_hp = (unsigned int) val; + break; + case UDT_SP: + status->set_sp(bl, (unsigned int) val, 0); + break; + case UDT_MAXSP: + mc->base_status.max_sp = (unsigned int) val; + break; + case UDT_MASTERCID: + mc->mercenary.char_id = (uint32) val; + break; + case UDT_MAPIDXY: + unit->warp(bl, (short) val, (short) val2, (short) val3, CLR_TELEPORT); + break; + case UDT_WALKTOXY: + if (!unit->walktoxy(bl, (short) val, (short) val2, 2)) + unit->movepos(bl, (short) val, (short) val2, 0, 0); + break; + case UDT_SPEED: + mc->base_status.size = (unsigned char) val; + status->calc_misc(bl, &mc->base_status, mc->db->lv); + break; + case UDT_LOOKDIR: + unit->setdir(bl, (unsigned char) val); + break; + case UDT_CANMOVETICK: + mc->ud.canmove_tick = (int64) val; + break; + case UDT_STR: + mc->base_status.str = (unsigned short) val; + status->calc_misc(bl, &mc->base_status, mc->db->lv); + break; + case UDT_AGI: + mc->base_status.agi = (unsigned short) val; + status->calc_misc(bl, &mc->base_status, mc->db->lv); + break; + case UDT_VIT: + mc->base_status.vit = (unsigned short) val; + status->calc_misc(bl, &mc->base_status, mc->db->lv); + break; + case UDT_INT: + mc->base_status.int_ = (unsigned short) val; + status->calc_misc(bl, &mc->base_status, mc->db->lv); + break; + case UDT_DEX: + mc->base_status.dex = (unsigned short) val; + status->calc_misc(bl, &mc->base_status, mc->db->lv); + break; + case UDT_LUK: + mc->base_status.luk = (unsigned short) val; + status->calc_misc(bl, &mc->base_status, mc->db->lv); + break; + case UDT_ATKRANGE: + mc->base_status.rhw.range = (unsigned short) val; + break; + case UDT_ATKMIN: + mc->base_status.rhw.atk = (unsigned short) val; + break; + case UDT_ATKMAX: + mc->base_status.rhw.atk2 = (unsigned short) val; + break; + case UDT_MATKMIN: + mc->base_status.matk_min = (unsigned short) val; + break; + case UDT_MATKMAX: + mc->base_status.matk_max = (unsigned short) val; + break; + case UDT_DEF: + mc->base_status.def = (defType) val; + break; + case UDT_MDEF: + mc->base_status.mdef = (defType) val; + break; + case UDT_HIT: + mc->base_status.hit = (short) val; + break; + case UDT_FLEE: + mc->base_status.flee = (short) val; + break; + case UDT_PDODGE: + mc->base_status.flee2 = (short) val; + break; + case UDT_CRIT: + mc->base_status.cri = (short) val; + break; + case UDT_RACE: + mc->base_status.race = (unsigned char) val; + break; + case UDT_ELETYPE: + mc->base_status.def_ele = (unsigned char) val; + break; + case UDT_ELELEVEL: + mc->base_status.ele_lv = (unsigned char) val; + break; + case UDT_AMOTION: + mc->base_status.amotion = (unsigned short) val; + break; + case UDT_ADELAY: + mc->base_status.adelay = (unsigned short) val; + break; + case UDT_DMOTION: + mc->base_status.dmotion = (unsigned short) val; + break; + case UDT_MERC_KILLCOUNT: + mc->mercenary.kill_count = (unsigned int) val; + break; + case UDT_LIFETIME: + mc->mercenary.life_time = (unsigned int) val; + break; + default: + ShowWarning("buildin_setunitdata: Invalid data type '%s' for mercenary unit.\n", udtype); + script_pushint(st, 0); + return false; + } + + clif->mercenary_info(map->charid2sd(mc->mercenary.char_id)); + clif->mercenary_skillblock(map->charid2sd(mc->mercenary.char_id)); + } + break; + case BL_ELEM: + { + struct elemental_data *ed = BL_UCAST(BL_ELEM, bl); + + nullpo_retr(false, ed); + + switch (type) + { + case UDT_SIZE: + ed->base_status.size = (unsigned char) val; + break; + case UDT_HP: + status->set_hp(bl, (unsigned int) val, 0); + break; + case UDT_MAXHP: + ed->base_status.max_hp = (unsigned int) val; + break; + case UDT_SP: + status->set_sp(bl, (unsigned int) val, 0); + break; + case UDT_MAXSP: + ed->base_status.max_sp = (unsigned int) val; + break; + case UDT_MASTERCID: + ed->elemental.char_id = val; + break; + case UDT_MAPIDXY: + unit->warp(bl, (short) val, (short) val2, (short) val3, CLR_TELEPORT); + break; + case UDT_WALKTOXY: + if (!unit->walktoxy(bl, (short) val, (short) val2, 2)) + unit->movepos(bl, (short) val, (short) val2, 0, 0); + break; + case UDT_SPEED: + ed->base_status.speed = (unsigned short) val; + status->calc_misc(bl, &ed->base_status, ed->db->lv); + break; + case UDT_LOOKDIR: + unit->setdir(bl, (unsigned char) val); + break; + case UDT_CANMOVETICK: + ed->ud.canmove_tick = (int64) val; + break; + case UDT_STR: + ed->base_status.str = (unsigned short) val; + status->calc_misc(bl, &ed->base_status, ed->db->lv); + break; + case UDT_AGI: + ed->base_status.agi = (unsigned short) val; + status->calc_misc(bl, &ed->base_status, ed->db->lv); + break; + case UDT_VIT: + ed->base_status.vit = (unsigned short) val; + status->calc_misc(bl, &ed->base_status, ed->db->lv); + break; + case UDT_INT: + ed->base_status.int_ = (unsigned short) val; + status->calc_misc(bl, &ed->base_status, ed->db->lv); + break; + case UDT_DEX: + ed->base_status.dex = (unsigned short) val; + status->calc_misc(bl, &ed->base_status, ed->db->lv); + break; + case UDT_LUK: + ed->base_status.luk = (unsigned short) val; + status->calc_misc(bl, &ed->base_status, ed->db->lv); + break; + case UDT_ATKRANGE: + ed->base_status.rhw.range = (unsigned short) val; + break; + case UDT_ATKMIN: + ed->base_status.rhw.atk = (unsigned short) val; + break; + case UDT_ATKMAX: + ed->base_status.rhw.atk2 = (unsigned short) val; + break; + case UDT_MATKMIN: + ed->base_status.matk_min = (unsigned short) val; + break; + case UDT_MATKMAX: + ed->base_status.matk_max = (unsigned short) val; + break; + case UDT_DEF: + ed->base_status.def = (defType) val; + break; + case UDT_MDEF: + ed->base_status.mdef = (defType) val; + break; + case UDT_HIT: + ed->base_status.hit = (short) val; + break; + case UDT_FLEE: + ed->base_status.flee = (short) val; + break; + case UDT_PDODGE: + ed->base_status.flee2 = (short) val; + break; + case UDT_CRIT: + ed->base_status.cri = (short) val; + break; + case UDT_RACE: + ed->base_status.race = (unsigned char) val; + break; + case UDT_ELETYPE: + ed->base_status.def_ele = (unsigned char) val; + break; + case UDT_ELELEVEL: + ed->base_status.ele_lv = (unsigned char) val; + break; + case UDT_AMOTION: + ed->base_status.amotion = (unsigned short) val; + break; + case UDT_ADELAY: + ed->base_status.adelay = (unsigned short) val; + break; + case UDT_DMOTION: + ed->base_status.dmotion = (unsigned short) val; + break; + case UDT_LIFETIME: + ed->elemental.life_time = (int) val; + break; + default: + ShowWarning("buildin_setunitdata: Invalid data type '%s' for elemental unit.\n", udtype); + script_pushint(st, 0); + return false; + } + clif->elemental_info(ed->master); + } + break; + case BL_NPC: + { + struct npc_data *nd = BL_UCAST(BL_NPC, bl); + + nullpo_retr(false, nd); + + switch (type) + { + case UDT_SIZE: + nd->status.size = (unsigned char) val; + break; + case UDT_LEVEL: + nd->level = (unsigned short) val; + break; + case UDT_HP: + status->set_hp(bl, (unsigned int) val, 0); + break; + case UDT_MAXHP: + nd->status.max_hp = (unsigned int) val; + break; + case UDT_SP: + status->set_sp(bl, (unsigned int) val, 0); + break; + case UDT_MAXSP: + nd->status.max_sp = (unsigned int) val; + break; + case UDT_MAPIDXY: + unit->warp(bl, (short) val, (short) val2, (short) val3, CLR_TELEPORT); + break; + case UDT_WALKTOXY: + if (!unit->walktoxy(bl, (short) val, (short) val2, 2)) + unit->movepos(bl, (short) val, (short) val2, 0, 0); + break; + case UDT_CLASS: + npc->setclass(nd, (short) val); + break; + case UDT_SPEED: + nd->speed = (short) val; + status->calc_misc(bl, &nd->status, nd->level); + break; + case UDT_LOOKDIR: + unit->setdir(bl, (unsigned char) val); + break; + case UDT_STR: + nd->status.str = (unsigned short) val; + status->calc_misc(bl, &nd->status, nd->level); + break; + case UDT_AGI: + nd->status.agi = (unsigned short) val; + status->calc_misc(bl, &nd->status, nd->level); + break; + case UDT_VIT: + nd->status.vit = (unsigned short) val; + status->calc_misc(bl, &nd->status, nd->level); + break; + case UDT_INT: + nd->status.int_ = (unsigned short) val; + status->calc_misc(bl, &nd->status, nd->level); + break; + case UDT_DEX: + nd->status.dex = (unsigned short) val; + status->calc_misc(bl, &nd->status, nd->level); + break; + case UDT_LUK: + nd->status.luk = (unsigned short) val; + status->calc_misc(bl, &nd->status, nd->level); + break; + case UDT_STATPOINT: + nd->stat_point = (unsigned short) val; + break; + case UDT_ATKRANGE: + nd->status.rhw.range = (unsigned short) val; + break; + case UDT_ATKMIN: + nd->status.rhw.atk = (unsigned short) val; + break; + case UDT_ATKMAX: + nd->status.rhw.atk2 = (unsigned short) val; + break; + case UDT_MATKMIN: + nd->status.matk_min = (unsigned short) val; + break; + case UDT_MATKMAX: + nd->status.matk_max = (unsigned short) val; + break; + case UDT_DEF: + nd->status.def = (defType) val; + break; + case UDT_MDEF: + nd->status.mdef = (defType) val; + break; + case UDT_HIT: + nd->status.hit = (short) val; + break; + case UDT_FLEE: + nd->status.flee = (short) val; + break; + case UDT_PDODGE: + nd->status.flee2 = (short) val; + break; + case UDT_CRIT: + nd->status.cri = (short) val; + break; + case UDT_RACE: + nd->status.race = (unsigned char) val; + break; + case UDT_ELETYPE: + nd->status.def_ele = (unsigned char) val; + break; + case UDT_ELELEVEL: + nd->status.ele_lv = (unsigned char) val; + break; + case UDT_AMOTION: + nd->status.amotion = (unsigned short) val; + break; + case UDT_ADELAY: + nd->status.adelay = (unsigned short) val; + break; + case UDT_DMOTION: + nd->status.dmotion = (unsigned short) val; + break; + default: + ShowWarning("buildin_setunitdata: Invalid data type '%s' for NPC unit.\n", udtype); + script_pushint(st, 0); + return false; + } + } + break; + default: + ShowError("buildin_setunitdata: Unknown object!\n"); + script_pushint(st, 0); + return false; + } // end of bl->type switch + + script_pushint(st, 1); + return true; +} + +/** + * Retrieves real-time data for a game object. + * Getunitdata <GUID>,<DataType>{,<Variable>} + * @param1 GUID Game object unique Id. + * @param2 DataType Type of Data to be set for the unit. + * @param3 Variable array reference to store data into. (used for UDT_MAPIDXY) + * @return 0 on failure, <value> on success + */ +BUILDIN(getunitdata) +{ + struct block_list *bl; + const char *udtype = NULL; + const struct map_session_data *sd = NULL; + int type = 0; + char* name = NULL; + struct script_data *data = script_hasdata(st,4)?script_getdata(st, 4):NULL; + + bl = map->id2bl(script_getnum(st, 2)); + + if (bl == NULL) { + ShowWarning("buildin_getunitdata: Error in finding object with given GID %d!\n", script_getnum(st, 2)); + script_pushint(st, 0); + return false; + } + + type = script_getnum(st, 3); + + /* Type check */ + if (type < UDT_SIZE || type >= UDT_MAX) { + ShowError("buildin_getunitdata: Invalid unit data type %d provided.\n", type); + script_pushint(st, 0); + return false; + } + + /* Argument checks */ + if (type == UDT_MAPIDXY) { + if (data == NULL || !data_isreference(data)) { + ShowWarning("buildin_getunitdata: Error in argument 3. Please provide a reference variable to store values in.\n"); + script_pushint(st, 0); + return false; + } + + name = reference_getname(data); + + if (not_server_variable(*name)) { + sd = script->rid2sd(st); + if (sd == NULL) { + ShowWarning("buildin_getunitdata: Player not attached! Cannot use player variable %s.\n",name); + script_pushint(st, 0); + return true;// no player attached + } + } + } + +#define getunitdata_sub(idx__,var__) script->setd_sub(st,NULL,name,(idx__),(void *)h64BPTRSIZE((int)(var__)),data->ref); + + switch (bl->type) { + case BL_MOB: + { + const struct mob_data *md = BL_UCAST(BL_MOB, bl); + + nullpo_retr(false, md); + + switch (type) + { + case UDT_TYPE: script_pushint(st, BL_MOB); break; + case UDT_SIZE: script_pushint(st, md->status.size); break; + case UDT_LEVEL: script_pushint(st, md->level); break; + case UDT_HP: script_pushint(st, md->status.hp); break; + case UDT_MAXHP: script_pushint(st, md->status.max_hp); break; + case UDT_SP: script_pushint(st, md->status.sp); break; + case UDT_MAXSP: script_pushint(st, md->status.max_sp); break; + case UDT_MAPIDXY: + getunitdata_sub(0, md->bl.m); + getunitdata_sub(1, md->bl.x); + getunitdata_sub(2, md->bl.y); + break; + case UDT_SPEED: script_pushint(st, md->status.speed); break; + case UDT_MODE: script_pushint(st, md->status.mode); break; + case UDT_AI: script_pushint(st, md->special_state.ai); break; + case UDT_SCOPTION: script_pushint(st, md->sc.option); break; + case UDT_SEX: script_pushint(st, md->vd->sex); break; + case UDT_CLASS: script_pushint(st, md->vd->class); break; + case UDT_HAIRSTYLE: script_pushint(st, md->vd->hair_style); break; + case UDT_HAIRCOLOR: script_pushint(st, md->vd->hair_color); break; + case UDT_HEADBOTTOM: script_pushint(st, md->vd->head_bottom); break; + case UDT_HEADMIDDLE: script_pushint(st, md->vd->head_mid); break; + case UDT_HEADTOP: script_pushint(st, md->vd->head_top); break; + case UDT_CLOTHCOLOR: script_pushint(st, md->vd->cloth_color); break; + case UDT_SHIELD: script_pushint(st, md->vd->shield); break; + case UDT_WEAPON: script_pushint(st, md->vd->weapon); break; + case UDT_LOOKDIR: script_pushint(st, md->ud.dir); break; + case UDT_CANMOVETICK: script_pushint(st, md->ud.canmove_tick); break; + case UDT_STR: script_pushint(st, md->status.str); break; + case UDT_AGI: script_pushint(st, md->status.agi); break; + case UDT_VIT: script_pushint(st, md->status.vit); break; + case UDT_INT: script_pushint(st, md->status.int_); break; + case UDT_DEX: script_pushint(st, md->status.dex); break; + case UDT_LUK: script_pushint(st, md->status.luk); break; + case UDT_ATKRANGE: script_pushint(st, md->status.rhw.range); break; + case UDT_ATKMIN: script_pushint(st, md->status.rhw.atk); break; + case UDT_ATKMAX: script_pushint(st, md->status.rhw.atk2); break; + case UDT_MATKMIN: script_pushint(st, md->status.matk_min); break; + case UDT_MATKMAX: script_pushint(st, md->status.matk_max); break; + case UDT_DEF: script_pushint(st, md->status.def); break; + case UDT_MDEF: script_pushint(st, md->status.mdef); break; + case UDT_HIT: script_pushint(st, md->status.hit); break; + case UDT_FLEE: script_pushint(st, md->status.flee); break; + case UDT_PDODGE: script_pushint(st, md->status.flee2); break; + case UDT_CRIT: script_pushint(st, md->status.cri); break; + case UDT_RACE: script_pushint(st, md->status.race); break; + case UDT_ELETYPE: script_pushint(st, md->status.def_ele); break; + case UDT_ELELEVEL: script_pushint(st, md->status.ele_lv); break; + case UDT_AMOTION: script_pushint(st, md->status.amotion); break; + case UDT_ADELAY: script_pushint(st, md->status.adelay); break; + case UDT_DMOTION: script_pushint(st, md->status.dmotion); break; + default: + ShowWarning("buildin_getunitdata: Invalid data type '%s' for Mob unit.\n", udtype); + script_pushint(st, 0); + return false; + } + } + break; + case BL_HOM: + { + const struct homun_data *hd = BL_UCAST(BL_HOM, bl); + + nullpo_retr(false, hd); + + switch (type) + { + case UDT_TYPE: script_pushint(st, BL_HOM); break; + case UDT_SIZE: script_pushint(st, hd->base_status.size); break; + case UDT_LEVEL: script_pushint(st, hd->homunculus.level); break; + case UDT_HP: script_pushint(st, hd->base_status.hp); break; + case UDT_MAXHP: script_pushint(st, hd->base_status.max_hp); break; + case UDT_SP: script_pushint(st, hd->base_status.sp); break; + case UDT_MAXSP: script_pushint(st, hd->base_status.max_sp); break; + case UDT_MAPIDXY: + getunitdata_sub(0, hd->bl.m); + getunitdata_sub(1, hd->bl.x); + getunitdata_sub(2, hd->bl.y); + break; + case UDT_SPEED: script_pushint(st, hd->base_status.speed); break; + case UDT_LOOKDIR: script_pushint(st, hd->ud.dir); break; + case UDT_CANMOVETICK: script_pushint(st, hd->ud.canmove_tick); break; + case UDT_MODE: script_pushint(st, hd->base_status.mode); break; + case UDT_STR: script_pushint(st, hd->base_status.str); break; + case UDT_AGI: script_pushint(st, hd->base_status.agi); break; + case UDT_VIT: script_pushint(st, hd->base_status.vit); break; + case UDT_INT: script_pushint(st, hd->base_status.int_); break; + case UDT_DEX: script_pushint(st, hd->base_status.dex); break; + case UDT_LUK: script_pushint(st, hd->base_status.luk); break; + case UDT_ATKRANGE: script_pushint(st, hd->base_status.rhw.range); break; + case UDT_ATKMIN: script_pushint(st, hd->base_status.rhw.atk); break; + case UDT_ATKMAX: script_pushint(st, hd->base_status.rhw.atk2); break; + case UDT_MATKMIN: script_pushint(st, hd->base_status.matk_min); break; + case UDT_MATKMAX: script_pushint(st, hd->base_status.matk_max); break; + case UDT_DEF: script_pushint(st, hd->base_status.def); break; + case UDT_MDEF: script_pushint(st, hd->base_status.mdef); break; + case UDT_HIT: script_pushint(st, hd->base_status.hit); break; + case UDT_FLEE: script_pushint(st, hd->base_status.flee); break; + case UDT_PDODGE: script_pushint(st, hd->base_status.flee2); break; + case UDT_CRIT: script_pushint(st, hd->base_status.cri); break; + case UDT_RACE: script_pushint(st, hd->base_status.race); break; + case UDT_ELETYPE: script_pushint(st, hd->base_status.def_ele); break; + case UDT_ELELEVEL: script_pushint(st, hd->base_status.ele_lv); break; + case UDT_AMOTION: script_pushint(st, hd->base_status.amotion); break; + case UDT_ADELAY: script_pushint(st, hd->base_status.adelay); break; + case UDT_DMOTION: script_pushint(st, hd->base_status.dmotion); break; + case UDT_MASTERCID: script_pushint(st, hd->homunculus.char_id); break; + case UDT_HUNGER: script_pushint(st, hd->homunculus.hunger); break; + case UDT_INTIMACY: script_pushint(st, hd->homunculus.intimacy); break; + default: + ShowWarning("buildin_getunitdata: Invalid data type '%s' for Homunculus unit.\n", udtype); + script_pushint(st, 0); + return false; + } + } + break; + case BL_PET: + { + const struct pet_data *pd = BL_UCAST(BL_PET, bl); + + nullpo_retr(false, pd); + + switch (type) + { + case UDT_TYPE: script_pushint(st, BL_PET); break; + case UDT_SIZE: script_pushint(st, pd->status.size); break; + case UDT_LEVEL: script_pushint(st, pd->pet.level); break; + case UDT_HP: script_pushint(st, pd->status.hp); break; + case UDT_MAXHP: script_pushint(st, pd->status.max_hp); break; + case UDT_SP: script_pushint(st, pd->status.sp); break; + case UDT_MAXSP: script_pushint(st, pd->status.max_sp); break; + case UDT_MAPIDXY: + getunitdata_sub(0, pd->bl.m); + getunitdata_sub(1, pd->bl.x); + getunitdata_sub(2, pd->bl.y); + break; + case UDT_SPEED: script_pushint(st, pd->status.speed); break; + case UDT_LOOKDIR: script_pushint(st, pd->ud.dir); break; + case UDT_CANMOVETICK: script_pushint(st, pd->ud.canmove_tick); break; + case UDT_MODE: script_pushint(st, pd->status.mode); break; + case UDT_STR: script_pushint(st, pd->status.str); break; + case UDT_AGI: script_pushint(st, pd->status.agi); break; + case UDT_VIT: script_pushint(st, pd->status.vit); break; + case UDT_INT: script_pushint(st, pd->status.int_); break; + case UDT_DEX: script_pushint(st, pd->status.dex); break; + case UDT_LUK: script_pushint(st, pd->status.luk); break; + case UDT_ATKRANGE: script_pushint(st, pd->status.rhw.range); break; + case UDT_ATKMIN: script_pushint(st, pd->status.rhw.atk); break; + case UDT_ATKMAX: script_pushint(st, pd->status.rhw.atk2); break; + case UDT_MATKMIN: script_pushint(st, pd->status.matk_min); break; + case UDT_MATKMAX: script_pushint(st, pd->status.matk_max); break; + case UDT_DEF: script_pushint(st, pd->status.def); break; + case UDT_MDEF: script_pushint(st, pd->status.mdef); break; + case UDT_HIT: script_pushint(st, pd->status.hit); break; + case UDT_FLEE: script_pushint(st, pd->status.flee); break; + case UDT_PDODGE: script_pushint(st, pd->status.flee2); break; + case UDT_CRIT: script_pushint(st, pd->status.cri); break; + case UDT_RACE: script_pushint(st, pd->status.race); break; + case UDT_ELETYPE: script_pushint(st, pd->status.def_ele); break; + case UDT_ELELEVEL: script_pushint(st, pd->status.ele_lv); break; + case UDT_AMOTION: script_pushint(st, pd->status.amotion); break; + case UDT_ADELAY: script_pushint(st, pd->status.adelay); break; + case UDT_DMOTION: script_pushint(st, pd->status.dmotion); break; + case UDT_MASTERAID: script_pushint(st, pd->pet.account_id); break; + case UDT_HUNGER: script_pushint(st, pd->pet.hungry); break; + case UDT_INTIMACY: script_pushint(st, pd->pet.intimate); break; + default: + ShowWarning("buildin_getunitdata: Invalid data type '%s' for Pet unit.\n", udtype); + script_pushint(st, 0); + return false; + } + } + break; + case BL_MER: + { + const struct mercenary_data *mc = BL_UCAST(BL_MER, bl); + + nullpo_retr(false, mc); + + switch (type) + { + case UDT_TYPE: script_pushint(st, BL_MER); break; + case UDT_SIZE: script_pushint(st, mc->base_status.size); break; + case UDT_HP: script_pushint(st, mc->base_status.hp); break; + case UDT_MAXHP: script_pushint(st, mc->base_status.max_hp); break; + case UDT_SP: script_pushint(st, mc->base_status.sp); break; + case UDT_MAXSP: script_pushint(st, mc->base_status.max_sp); break; + case UDT_MAPIDXY: + getunitdata_sub(0, mc->bl.m); + getunitdata_sub(1, mc->bl.x); + getunitdata_sub(2, mc->bl.y); + break; + case UDT_SPEED: script_pushint(st, mc->base_status.speed); break; + case UDT_LOOKDIR: script_pushint(st, mc->ud.dir); break; + case UDT_CANMOVETICK: script_pushint(st, mc->ud.canmove_tick); break; + case UDT_MODE: script_pushint(st, mc->base_status.mode); break; + case UDT_STR: script_pushint(st, mc->base_status.str); break; + case UDT_AGI: script_pushint(st, mc->base_status.agi); break; + case UDT_VIT: script_pushint(st, mc->base_status.vit); break; + case UDT_INT: script_pushint(st, mc->base_status.int_); break; + case UDT_DEX: script_pushint(st, mc->base_status.dex); break; + case UDT_LUK: script_pushint(st, mc->base_status.luk); break; + case UDT_ATKRANGE: script_pushint(st, mc->base_status.rhw.range); break; + case UDT_ATKMIN: script_pushint(st, mc->base_status.rhw.atk); break; + case UDT_ATKMAX: script_pushint(st, mc->base_status.rhw.atk2); break; + case UDT_MATKMIN: script_pushint(st, mc->base_status.matk_min); break; + case UDT_MATKMAX: script_pushint(st, mc->base_status.matk_max); break; + case UDT_DEF: script_pushint(st, mc->base_status.def); break; + case UDT_MDEF: script_pushint(st, mc->base_status.mdef); break; + case UDT_HIT: script_pushint(st, mc->base_status.hit); break; + case UDT_FLEE: script_pushint(st, mc->base_status.flee); break; + case UDT_PDODGE: script_pushint(st, mc->base_status.flee2); break; + case UDT_CRIT: script_pushint(st, mc->base_status.cri); break; + case UDT_RACE: script_pushint(st, mc->base_status.race); break; + case UDT_ELETYPE: script_pushint(st, mc->base_status.def_ele); break; + case UDT_ELELEVEL: script_pushint(st, mc->base_status.ele_lv); break; + case UDT_AMOTION: script_pushint(st, mc->base_status.amotion); break; + case UDT_ADELAY: script_pushint(st, mc->base_status.adelay); break; + case UDT_DMOTION: script_pushint(st, mc->base_status.dmotion); break; + case UDT_MASTERCID: script_pushint(st, mc->mercenary.char_id); break; + case UDT_MERC_KILLCOUNT: script_pushint(st, mc->mercenary.kill_count); break; + case UDT_LIFETIME: script_pushint(st, mc->mercenary.life_time); break; + default: + ShowWarning("buildin_getunitdata: Invalid data type '%s' for Mercenary unit.\n", udtype); + script_pushint(st, 0); + return false; + } + } + break; + case BL_ELEM: + { + const struct elemental_data *ed = BL_UCAST(BL_ELEM, bl); + + nullpo_retr(false, ed); + + switch (type) + { + case UDT_TYPE: script_pushint(st, BL_ELEM); break; + case UDT_SIZE: script_pushint(st, ed->base_status.size); break; + case UDT_HP: script_pushint(st, ed->base_status.hp); break; + case UDT_MAXHP: script_pushint(st, ed->base_status.max_hp); break; + case UDT_SP: script_pushint(st, ed->base_status.sp); break; + case UDT_MAXSP: script_pushint(st, ed->base_status.max_sp); break; + case UDT_MAPIDXY: + getunitdata_sub(0, ed->bl.m); + getunitdata_sub(1, ed->bl.x); + getunitdata_sub(2, ed->bl.y); + break; + case UDT_SPEED: script_pushint(st, ed->base_status.speed); break; + case UDT_LOOKDIR: script_pushint(st, ed->ud.dir); break; + case UDT_CANMOVETICK: script_pushint(st, ed->ud.canmove_tick); break; + case UDT_MODE: script_pushint(st, ed->base_status.mode); break; + case UDT_STR: script_pushint(st, ed->base_status.str); break; + case UDT_AGI: script_pushint(st, ed->base_status.agi); break; + case UDT_VIT: script_pushint(st, ed->base_status.vit); break; + case UDT_INT: script_pushint(st, ed->base_status.int_); break; + case UDT_DEX: script_pushint(st, ed->base_status.dex); break; + case UDT_LUK: script_pushint(st, ed->base_status.luk); break; + case UDT_ATKRANGE: script_pushint(st, ed->base_status.rhw.range); break; + case UDT_ATKMIN: script_pushint(st, ed->base_status.rhw.atk); break; + case UDT_ATKMAX: script_pushint(st, ed->base_status.rhw.atk2); break; + case UDT_MATKMIN: script_pushint(st, ed->base_status.matk_min); break; + case UDT_MATKMAX: script_pushint(st, ed->base_status.matk_max); break; + case UDT_DEF: script_pushint(st, ed->base_status.def); break; + case UDT_MDEF: script_pushint(st, ed->base_status.mdef); break; + case UDT_HIT: script_pushint(st, ed->base_status.hit); break; + case UDT_FLEE: script_pushint(st, ed->base_status.flee); break; + case UDT_PDODGE: script_pushint(st, ed->base_status.flee2); break; + case UDT_CRIT: script_pushint(st, ed->base_status.cri); break; + case UDT_RACE: script_pushint(st, ed->base_status.race); break; + case UDT_ELETYPE: script_pushint(st, ed->base_status.def_ele); break; + case UDT_ELELEVEL: script_pushint(st, ed->base_status.ele_lv); break; + case UDT_AMOTION: script_pushint(st, ed->base_status.amotion); break; + case UDT_ADELAY: script_pushint(st, ed->base_status.adelay); break; + case UDT_DMOTION: script_pushint(st, ed->base_status.dmotion); break; + case UDT_MASTERCID: script_pushint(st, ed->elemental.char_id); break; + default: + ShowWarning("buildin_getunitdata: Invalid data type '%s' for Elemental unit.\n", udtype); + script_pushint(st, 0); + return false; + } + } + break; + case BL_NPC: + { + const struct npc_data *nd = BL_UCAST(BL_NPC, bl); + + nullpo_retr(false, nd); + + switch (type) + { + case UDT_TYPE: script_pushint(st, BL_NPC); break; + case UDT_SIZE: script_pushint(st, nd->status.size); break; + case UDT_HP: script_pushint(st, nd->status.hp); break; + case UDT_MAXHP: script_pushint(st, nd->status.max_hp); break; + case UDT_SP: script_pushint(st, nd->status.sp); break; + case UDT_MAXSP: script_pushint(st, nd->status.max_sp); break; + case UDT_MAPIDXY: + getunitdata_sub(0, bl->m); + getunitdata_sub(1, bl->x); + getunitdata_sub(2, bl->y); + break; + case UDT_SPEED: script_pushint(st, nd->status.speed); break; + case UDT_LOOKDIR: script_pushint(st, nd->ud->dir); break; + case UDT_CANMOVETICK: script_pushint(st, nd->ud->canmove_tick); break; + case UDT_MODE: script_pushint(st, nd->status.mode); break; + case UDT_STR: script_pushint(st, nd->status.str); break; + case UDT_AGI: script_pushint(st, nd->status.agi); break; + case UDT_VIT: script_pushint(st, nd->status.vit); break; + case UDT_INT: script_pushint(st, nd->status.int_); break; + case UDT_DEX: script_pushint(st, nd->status.dex); break; + case UDT_LUK: script_pushint(st, nd->status.luk); break; + case UDT_ATKRANGE: script_pushint(st, nd->status.rhw.range); break; + case UDT_ATKMIN: script_pushint(st, nd->status.rhw.atk); break; + case UDT_ATKMAX: script_pushint(st, nd->status.rhw.atk2); break; + case UDT_MATKMIN: script_pushint(st, nd->status.matk_min); break; + case UDT_MATKMAX: script_pushint(st, nd->status.matk_max); break; + case UDT_DEF: script_pushint(st, nd->status.def); break; + case UDT_MDEF: script_pushint(st, nd->status.mdef); break; + case UDT_HIT: script_pushint(st, nd->status.hit); break; + case UDT_FLEE: script_pushint(st, nd->status.flee); break; + case UDT_PDODGE: script_pushint(st, nd->status.flee2); break; + case UDT_CRIT: script_pushint(st, nd->status.cri); break; + case UDT_RACE: script_pushint(st, nd->status.race); break; + case UDT_ELETYPE: script_pushint(st, nd->status.def_ele); break; + case UDT_ELELEVEL: script_pushint(st, nd->status.ele_lv); break; + case UDT_AMOTION: script_pushint(st, nd->status.amotion); break; + case UDT_ADELAY: script_pushint(st, nd->status.adelay); break; + case UDT_DMOTION: script_pushint(st, nd->status.dmotion); break; + default: + ShowWarning("buildin_getunitdata: Invalid data type '%s' for NPC unit.\n", udtype); + script_pushint(st, 0); + return false; + } + } + break; + default: + ShowError("buildin_getunitdata: Unknown object!\n"); + script_pushint(st, 0); + return false; + } // end of bl->type switch + +#undef getunitdata_sub + + return false; +} + +/** + * Gets the name of a Unit. + * Supported types are [MOB|HOM|PET|NPC]. + * MER and ELEM don't support custom names. + * + * @command getunitname <GUID>; + * @param GUID Game Object Unique ID. + * @return boolean or Name of the game object. + */ +BUILDIN(getunitname) +{ + const struct block_list* bl = NULL; + + bl = map->id2bl(script_getnum(st, 2)); + + if (bl == NULL) { + ShowWarning("buildin_getunitname: Error in finding object with given game ID %d!\n", script_getnum(st, 2)); + script_pushconststr(st, "Unknown"); + return false; + } + + script_pushstrcopy(st, status->get_name(bl)); + + return true; +} + +/** + * Changes the name of a bl. + * Supported types are [MOB|HOM|PET]. + * For NPC see 'setnpcdisplay', MER and ELEM don't support custom names. + * + * @command setunitname <GUID>,<name>; + * @param GUID Game object unique ID. + * @param Name as string. + * @return boolean. + */ +BUILDIN(setunitname) +{ + struct block_list* bl = map->id2bl(script_getnum(st, 2)); + + if (bl == NULL) { + ShowWarning("buildin_setunitname: Game object with ID %d was not found!\n", script_getnum(st, 2)); + script_pushint(st, 0); + return false; + } + + switch (bl->type) { + case BL_MOB: + { + struct mob_data *md = BL_UCAST(BL_MOB, bl); + if (md == NULL) { + ShowWarning("buildin_setunitname: Error in finding object BL_MOB!\n"); + script_pushint(st, 0); + return false; + } + safestrncpy(md->name, script_getstr(st, 3), NAME_LENGTH); + } + break; + case BL_HOM: + { + struct homun_data *hd = BL_UCAST(BL_HOM, bl); + if (hd == NULL) { + ShowWarning("buildin_setunitname: Error in finding object BL_HOM!\n"); + script_pushint(st, 0); + return false; + } + safestrncpy(hd->homunculus.name, script_getstr(st, 3), NAME_LENGTH); + } + break; + case BL_PET: + { + struct pet_data *pd = BL_UCAST(BL_PET, bl); + if (pd == NULL) { + ShowWarning("buildin_setunitname: Error in finding object BL_PET!\n"); + script_pushint(st, 0); + return false; + } + safestrncpy(pd->pet.name, script_getstr(st, 3), NAME_LENGTH); + } + break; + default: + script_pushint(st, 0); + ShowWarning("buildin_setunitname: Unknown object type!\n"); + return false; + } + + script_pushint(st, 1); + clif->charnameack(0, bl); // Send update to client. + + return true; +} + /// Makes the unit walk to target position or target id /// Returns if it was successfull /// @@ -21141,6 +22736,11 @@ void script_parse_builtin(void) { // <--- [zBuffer] List of player cont commands // [zBuffer] List of mob control commands ---> BUILDIN_DEF(getunittype,"i"), + /* Unit Data */ + BUILDIN_DEF(setunitdata,"iiv??"), + BUILDIN_DEF(getunitdata,"ii?"), + BUILDIN_DEF(getunitname,"i"), + BUILDIN_DEF(setunitname,"is"), BUILDIN_DEF(unitwalk,"ii?"), BUILDIN_DEF(unitkill,"i"), BUILDIN_DEF(unitwarp,"isii"), diff --git a/src/map/script.h b/src/map/script.h index a69000991..7ee6d772b 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -350,6 +350,81 @@ enum navigation_service { }; /** + * Unit Types for script handling. + */ +enum script_unit_types { + UNIT_PC = 0, + UNIT_NPC, + UNIT_PET, + UNIT_MOB, + UNIT_HOM, + UNIT_MER, + UNIT_ELEM, +}; + +/** + * Unit Data Types for script handling. + */ +enum script_unit_data_types { + UDT_TYPE = 0, + UDT_SIZE, + UDT_LEVEL, + UDT_HP, + UDT_MAXHP, + UDT_SP, + UDT_MAXSP, + UDT_MASTERAID, + UDT_MASTERCID, + UDT_MAPIDXY, + UDT_WALKTOXY, + UDT_SPEED, + UDT_MODE, + UDT_AI, + UDT_SCOPTION, + UDT_SEX, + UDT_CLASS, + UDT_HAIRSTYLE, + UDT_HAIRCOLOR, + UDT_HEADBOTTOM, + UDT_HEADMIDDLE, + UDT_HEADTOP, + UDT_CLOTHCOLOR, + UDT_SHIELD, + UDT_WEAPON, + UDT_LOOKDIR, + UDT_CANMOVETICK, + UDT_STR, + UDT_AGI, + UDT_VIT, + UDT_INT, + UDT_DEX, + UDT_LUK, + UDT_ATKRANGE, + UDT_ATKMIN, + UDT_ATKMAX, + UDT_MATKMIN, + UDT_MATKMAX, + UDT_DEF, + UDT_MDEF, + UDT_HIT, + UDT_FLEE, + UDT_PDODGE, + UDT_CRIT, + UDT_RACE, + UDT_ELETYPE, + UDT_ELELEVEL, + UDT_AMOTION, + UDT_ADELAY, + UDT_DMOTION, + UDT_HUNGER, + UDT_INTIMACY, + UDT_LIFETIME, + UDT_MERC_KILLCOUNT, + UDT_STATPOINT, + UDT_MAX +}; + +/** * Structures **/ |