summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/map/npc.h4
-rw-r--r--src/map/script.c60
-rw-r--r--src/map/status.c38
-rw-r--r--src/map/status.h1
4 files changed, 97 insertions, 6 deletions
diff --git a/src/map/npc.h b/src/map/npc.h
index 0379ae634..041adb7b6 100644
--- a/src/map/npc.h
+++ b/src/map/npc.h
@@ -39,6 +39,10 @@ struct npc_data {
unsigned size : 2;
+ struct status_data status;
+ unsigned int level;
+ unsigned int stat_point;
+
void* chatdb; // pointer to a npc_parse struct (see npc_chat.c)
char* path;/* path dir */
enum npc_subtype subtype;
diff --git a/src/map/script.c b/src/map/script.c
index a02c33cf8..55f6d0283 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -17254,9 +17254,9 @@ BUILDIN_FUNC(cleanmap)
map_foreachinmap(atcommand_cleanfloor_sub, m, BL_ITEM);
} else {
x0 = script_getnum(st, 3);
- y0 = script_getnum(st, 4);
- x1 = script_getnum(st, 5);
- y1 = script_getnum(st, 6);
+ y0 = script_getnum(st, 4);
+ x1 = script_getnum(st, 5);
+ y1 = script_getnum(st, 6);
if (x0 > 0 && y0 > 0 && x1 > 0 && y1 > 0) {
map_foreachinarea(atcommand_cleanfloor_sub, m, x0, y0, x1, y1, BL_ITEM);
} else {
@@ -17267,7 +17267,54 @@ BUILDIN_FUNC(cleanmap)
return 0;
}
+/* Cast a skill on the attached player.
+ * useskilltopc <skill_id>, <skill_level>, <stat_point>, <npc_level>;
+ * useskilltopc "<skill_name>", <skill_level>, <stat_point>, <npc_level>; */
+BUILDIN_FUNC(useskilltopc)
+{
+ unsigned int skill_id;
+ unsigned short skill_level;
+ unsigned int stat_point;
+ unsigned int npc_level;
+ struct npc_data *nd;
+ struct map_session_data *sd;
+
+ skill_id = script_isstring(st, 2) ? skill_name2id(script_getstr(st, 2)) : script_getnum(st, 2);
+ skill_level = script_getnum(st, 3);
+ stat_point = script_getnum(st, 4);
+ npc_level = script_getnum(st, 5);
+ sd = script_rid2sd(st);
+ nd = (struct npc_data *)map_id2bl(sd->npc_id);
+
+ if (stat_point > battle_config.max_third_parameter) {
+ ShowError("useskilltopc: stat point exceeded maximum of %d.\n",battle_config.max_third_parameter );
+ return 1;
+ }
+ if (npc_level > MAX_LEVEL) {
+ ShowError("useskilltopc: level exceeded maximum of %d.\n", MAX_LEVEL);
+ return 1;
+ }
+ if (sd == NULL || nd == NULL) { //ain't possible, but I don't trust people.
+ return 1;
+ }
+
+ nd->level = npc_level;
+ nd->stat_point = stat_point;
+
+ if (!nd->status.hp) {
+ status_calc_npc(nd, true);
+ } else {
+ status_calc_npc(nd, false);
+ }
+ if (skill_get_inf(skill_id)&INF_GROUND_SKILL) {
+ unit_skilluse_pos(&nd->bl, sd->bl.x, sd->bl.y, skill_id, skill_level);
+ } else {
+ unit_skilluse_id(&nd->bl, sd->bl.id, skill_id, skill_level);
+ }
+
+ return 0;
+}
// declarations that were supposed to be exported from npc_chat.c
#ifdef PCRE_SUPPORT
@@ -17708,9 +17755,10 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(is_function,"s"),
BUILDIN_DEF(get_revision,""),
BUILDIN_DEF(freeloop,"i"),
- BUILDIN_DEF(getrandgroupitem, "ii"),
- BUILDIN_DEF(cleanmap, "s"),
- BUILDIN_DEF2(cleanmap, "cleanarea", "siiii"),
+ BUILDIN_DEF(getrandgroupitem,"ii"),
+ BUILDIN_DEF(cleanmap,"s"),
+ BUILDIN_DEF2(cleanmap,"cleanarea","siiii"),
+ BUILDIN_DEF(useskilltopc,"viii"),
/**
* @commands (script based)
**/
diff --git a/src/map/status.c b/src/map/status.c
index de1dde6ae..d4af092ad 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -3225,6 +3225,40 @@ int status_calc_elemental_(struct elemental_data *ed, bool first) {
return 0;
}
+int status_calc_npc_(struct npc_data *nd, bool first) {
+ struct status_data *status = &nd->status;
+
+ if (!nd)
+ return 0;
+
+ if (first) {
+ status->hp = 1;
+ status->sp = 1;
+ status->max_hp = 1;
+ status->max_sp = 1;
+
+ status->def_ele = ELE_NEUTRAL;
+ status->ele_lv = 1;
+ status->race = RC_DEMIHUMAN;
+ status->size = nd->size;
+ status->rhw.range = 1 + status->size;
+ status->mode = MD_CANMOVE|MD_CANATTACK;
+ status->speed = nd->speed;
+ }
+
+ status->str = nd->stat_point;
+ status->agi = nd->stat_point;
+ status->vit = nd->stat_point;
+ status->int_= nd->stat_point;
+ status->dex = nd->stat_point;
+ status->luk = nd->stat_point;
+
+ status_calc_misc(&nd->bl, status, nd->level);
+ status_cpy(&nd->status, status);
+
+ return 0;
+}
+
static unsigned short status_calc_str(struct block_list *,struct status_change *,int);
static unsigned short status_calc_agi(struct block_list *,struct status_change *,int);
static unsigned short status_calc_vit(struct block_list *,struct status_change *,int);
@@ -3963,6 +3997,7 @@ void status_calc_bl_(struct block_list* bl, enum scb_flag flag, bool first)
case BL_HOM: status_calc_homunculus_(BL_CAST(BL_HOM,bl), first); break;
case BL_MER: status_calc_mercenary_(BL_CAST(BL_MER,bl), first); break;
case BL_ELEM: status_calc_elemental_(BL_CAST(BL_ELEM,bl), first); break;
+ case BL_NPC: status_calc_npc_(BL_CAST(BL_NPC,bl), first); break;
}
}
@@ -5739,6 +5774,7 @@ int status_get_lv(struct block_list *bl) {
case BL_HOM: return ((TBL_HOM*)bl)->homunculus.level;
case BL_MER: return ((TBL_MER*)bl)->db->lv;
case BL_ELEM: return ((TBL_ELEM*)bl)->db->lv;
+ case BL_NPC: return ((TBL_NPC*)bl)->level;
}
return 1;
}
@@ -5767,6 +5803,7 @@ struct status_data *status_get_status_data(struct block_list *bl)
case BL_HOM: return &((TBL_HOM*)bl)->battle_status;
case BL_MER: return &((TBL_MER*)bl)->battle_status;
case BL_ELEM: return &((TBL_ELEM*)bl)->battle_status;
+ case BL_NPC: return &((TBL_NPC*)bl)->status;
default:
return &dummy_status;
}
@@ -5782,6 +5819,7 @@ struct status_data *status_get_base_status(struct block_list *bl)
case BL_HOM: return &((TBL_HOM*)bl)->base_status;
case BL_MER: return &((TBL_MER*)bl)->base_status;
case BL_ELEM: return &((TBL_ELEM*)bl)->base_status;
+ case BL_NPC: return &((TBL_NPC*)bl)->status;
default:
return NULL;
}
diff --git a/src/map/status.h b/src/map/status.h
index 1e9245af2..9e162faeb 100644
--- a/src/map/status.h
+++ b/src/map/status.h
@@ -1786,6 +1786,7 @@ int status_change_clear_buffs(struct block_list* bl, int type);
#define status_calc_homunculus(hd, first) status_calc_bl_(&(hd)->bl, SCB_ALL, first)
#define status_calc_mercenary(md, first) status_calc_bl_(&(md)->bl, SCB_ALL, first)
#define status_calc_elemental(ed, first) status_calc_bl_(&(ed)->bl, SCB_ALL, first)
+#define status_calc_npc(nd, first) status_calc_bl_(&(nd)->bl, SCB_ALL, first)
void status_calc_bl_(struct block_list *bl, enum scb_flag flag, bool first);
int status_calc_mob_(struct mob_data* md, bool first);