summaryrefslogtreecommitdiff
path: root/src/map/skill.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/skill.c')
-rw-r--r--src/map/skill.c107
1 files changed, 88 insertions, 19 deletions
diff --git a/src/map/skill.c b/src/map/skill.c
index 24fbe7892..c2a336d7e 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -47,6 +47,7 @@
#include "map/refine.h"
#include "map/script.h"
#include "map/status.h"
+#include "map/storage.h"
#include "map/unit.h"
#include "common/cbasetypes.h"
#include "common/ers.h"
@@ -370,6 +371,41 @@ static int skill_get_spiritball(int skill_id, int skill_lv)
}
/**
+ * Gets the index of the first required item for a skill at given level.
+ *
+ * @param skill_id The skill's ID.
+ * @param skill_lv The skill's level.
+ * @return The required item's index. Defaults to INDEX_NOT_FOUND (-1) in case of error or if no appropriate index was found.
+ *
+ **/
+static int skill_get_item_index(int skill_id, int skill_lv)
+{
+ if (skill_id == 0)
+ return INDEX_NOT_FOUND;
+
+ Assert_retr(INDEX_NOT_FOUND, skill_lv > 0);
+
+ int idx = skill->get_index(skill_id);
+
+ Assert_retr(INDEX_NOT_FOUND, idx != 0);
+
+ int item_index = INDEX_NOT_FOUND;
+ int level_index = skill_get_lvl_idx(skill_lv);
+
+ for (int i = 0; i < MAX_SKILL_ITEM_REQUIRE; i++) {
+ if (skill->dbs->db[idx].req_items.item[i].id == 0)
+ continue;
+
+ if (skill->dbs->db[idx].req_items.item[i].amount[level_index] != -1) {
+ item_index = i;
+ break;
+ }
+ }
+
+ return item_index;
+}
+
+/**
* Gets a skill's required item's ID by the skill's ID and the item's index.
*
* @param skill_id The skill's ID.
@@ -1613,11 +1649,15 @@ static int skill_additional_effect(struct block_list *src, struct block_list *bl
if( pc_iswug(sd) && (temp=pc->checkskill(sd,RA_WUGSTRIKE)) > 0 && rnd()%1000 <= sstatus->luk*3 )
skill->castend_damage_id(src,bl,RA_WUGSTRIKE,temp,tick,0);
// Gank
- if(dstmd && sd->weapontype != W_BOW &&
- (temp=pc->checkskill(sd,RG_SNATCHER)) > 0 &&
- (temp*15 + 55) + pc->checkskill(sd,TF_STEAL)*10 > rnd()%1000) {
- if(pc->steal_item(sd,bl,pc->checkskill(sd,TF_STEAL)))
- clif->skill_nodamage(src,bl,TF_STEAL,temp,1);
+ if (dstmd && sd->weapontype != W_BOW &&
+ (temp = pc->checkskill(sd, RG_SNATCHER)) > 0 &&
+#ifdef RENEWAL
+ (temp * 10) + pc->checkskill(sd, TF_STEAL) * 10 > rnd() % 1000) {
+#else
+ (temp * 15 + 55) + pc->checkskill(sd, TF_STEAL) * 10 > rnd() % 1000) {
+#endif
+ if (pc->steal_item(sd, bl, pc->checkskill(sd, TF_STEAL)))
+ clif->skill_nodamage(src, bl, TF_STEAL, temp, 1);
else
clif->skill_fail(sd, RG_SNATCHER, USESKILL_FAIL_LEVEL, 0, 0);
}
@@ -7937,7 +7977,14 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
}
if( sd ) {
int bonus = 100, potion = min(500+skill_lv,505);
- int item_idx = (skill_lv - 1) % MAX_SKILL_ITEM_REQUIRE;
+ int item_idx = skill->get_item_index(skill_id, skill_lv);
+
+ if (item_idx == INDEX_NOT_FOUND) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
+ map->freeblock_unlock();
+ return 1;
+ }
+
int item_id = skill->get_itemid(skill_id, item_idx);
int inventory_idx = pc->search_inventory(sd, item_id);
if (inventory_idx == INDEX_NOT_FOUND || item_id <= 0) {
@@ -11312,17 +11359,21 @@ static int skill_castend_map(struct map_session_data *sd, uint16 skill_id, const
return 0;
}
- switch(skill_id) {
+ switch (skill_id) {
case AL_TELEPORT:
- // The storage window is closed automatically by the client when there's
- // any kind of map change, so we need to restore it automatically
- // issue: 8027
- if(strcmp(mapname,"Random")==0)
- pc->randomwarp(sd,CLR_TELEPORT);
- else if (sd->menuskill_val > 1) //Need lv2 to be able to warp here.
- pc->setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT);
-
- clif->refresh_storagewindow(sd);
+ if (strcmp(mapname, "Random") == 0)
+ pc->randomwarp(sd, CLR_TELEPORT);
+ else if (sd->menuskill_val > 1) // Need lv2 to be able to warp here.
+ pc->setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT);
+
+ if (battle_config.teleport_close_storage == 1 && sd->state.storage_flag != STORAGE_FLAG_CLOSED) {
+ if (sd->state.storage_flag == STORAGE_FLAG_NORMAL)
+ storage->close(sd);
+ if (sd->state.storage_flag == STORAGE_FLAG_GUILD)
+ gstorage->close(sd);
+ } else {
+ clif->refresh_storagewindow(sd);
+ }
break;
case AL_WARP:
@@ -11797,7 +11848,13 @@ static int skill_castend_pos2(struct block_list *src, int x, int y, uint16 skill
// Slim Pitcher [Celest]
case CR_SLIMPITCHER:
if (sd) {
- int item_idx = (skill_lv - 1) % MAX_SKILL_ITEM_REQUIRE;
+ int item_idx = skill->get_item_index(skill_id, skill_lv);
+
+ if (item_idx == INDEX_NOT_FOUND) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
+ return 1;
+ }
+
int item_id = skill->get_itemid(skill_id, item_idx);
int inventory_idx = pc->search_inventory(sd, item_id);
int bonus;
@@ -11830,7 +11887,11 @@ static int skill_castend_pos2(struct block_list *src, int x, int y, uint16 skill
skill->castend_nodamage_id);
}
} else {
- int item_idx = (skill_lv - 1) % MAX_SKILL_ITEM_REQUIRE;
+ int item_idx = skill->get_item_index(skill_id, skill_lv);
+
+ if (item_idx == INDEX_NOT_FOUND)
+ return 1;
+
int item_id = skill->get_itemid(skill_id, item_idx);
struct item_data *item = itemdb->search(item_id);
int bonus;
@@ -17766,13 +17827,20 @@ static int skill_get_new_group_id(void)
static struct skill_unit_group *skill_initunitgroup(struct block_list *src, int count, uint16 skill_id, uint16 skill_lv, int unit_id, int limit, int interval)
{
- struct unit_data* ud = unit->bl2ud( src );
struct skill_unit_group* group;
int i;
if(!(skill_id && skill_lv)) return 0;
nullpo_retr(NULL, src);
+
+ struct unit_data *ud;
+
+ if (src->type == BL_NPC)
+ ud = unit->bl2ud2(src);
+ else
+ ud = unit->bl2ud(src);
+
nullpo_retr(NULL, ud);
// find a free spot to store the new unit group
@@ -23937,6 +24005,7 @@ void skill_defaults(void)
skill->get_sp_rate = skill_get_sp_rate;
skill->get_state = skill_get_state;
skill->get_spiritball = skill_get_spiritball;
+ skill->get_item_index = skill_get_item_index;
skill->get_itemid = skill_get_itemid;
skill->get_itemqty = skill_get_itemqty;
skill->get_item_any_flag = skill_get_item_any_flag;