Various cleanups.
* Added and cleaned up comments. * Added checks to prevent map server crashes. * Cleaned up some reports from CPPCheck. * Other various stylization cleanups.
This commit is contained in:
parent
ce090ce916
commit
2b870c24d5
349
src/map/battle.c
349
src/map/battle.c
@ -44,23 +44,33 @@ static struct eri *delay_damage_ers; //For battle delay damage structures.
|
||||
#define DAMAGE_SUBRATE(a) { damage -= (int64)damage * (a) / 100; }
|
||||
#define DAMAGE_ADDRATE(a) { damage += (int64)damage * (a) / 100; }
|
||||
|
||||
int battle_getcurrentskill(struct block_list *bl) { //Returns the current/last skill in use by this bl.
|
||||
/**
|
||||
* Returns the current/list skill used by the bl
|
||||
* @param bl
|
||||
* @return skill_id
|
||||
*/
|
||||
int battle_getcurrentskill(struct block_list *bl)
|
||||
{
|
||||
struct unit_data *ud;
|
||||
|
||||
if( bl->type == BL_SKILL ) {
|
||||
struct skill_unit * su = (struct skill_unit*)bl;
|
||||
return su->group?su->group->skill_id:0;
|
||||
struct skill_unit *su = (struct skill_unit*)bl;
|
||||
return (su && su->group?su->group->skill_id:0);
|
||||
}
|
||||
|
||||
ud = unit_bl2ud(bl);
|
||||
|
||||
return ud?ud->skill_id:0;
|
||||
return (ud?ud->skill_id:0);
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Get random targetting enemy
|
||||
*------------------------------------------*/
|
||||
static int battle_gettargeted_sub(struct block_list *bl, va_list ap) {
|
||||
/**
|
||||
* Get random targeting enemy
|
||||
* @param bl
|
||||
* @param ap
|
||||
* @return Found target (1) or not found (0)
|
||||
*/
|
||||
static int battle_gettargeted_sub(struct block_list *bl, va_list ap)
|
||||
{
|
||||
struct block_list **bl_list;
|
||||
struct unit_data *ud;
|
||||
int target_id;
|
||||
@ -87,7 +97,13 @@ static int battle_gettargeted_sub(struct block_list *bl, va_list ap) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct block_list* battle_gettargeted(struct block_list *target) {
|
||||
/**
|
||||
* Returns list of targets
|
||||
* @param target
|
||||
* @return Target list
|
||||
*/
|
||||
struct block_list* battle_gettargeted(struct block_list *target)
|
||||
{
|
||||
struct block_list *bl_list[24];
|
||||
int c = 0;
|
||||
nullpo_retr(NULL, target);
|
||||
@ -101,9 +117,14 @@ struct block_list* battle_gettargeted(struct block_list *target) {
|
||||
return bl_list[rnd()%c];
|
||||
}
|
||||
|
||||
|
||||
//Returns the id of the current targetted character of the passed bl. [Skotlex]
|
||||
int battle_gettarget(struct block_list* bl) {
|
||||
/**
|
||||
* Returns the ID of the current targeted character of the passed bl
|
||||
* @param bl
|
||||
* @return Target Unit ID
|
||||
* @author [Skotlex]
|
||||
*/
|
||||
int battle_gettarget(struct block_list* bl)
|
||||
{
|
||||
|
||||
switch (bl->type) {
|
||||
case BL_PC: return ((struct map_session_data*)bl)->ud.target;
|
||||
@ -117,7 +138,14 @@ int battle_gettarget(struct block_list* bl) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int battle_getenemy_sub(struct block_list *bl, va_list ap) {
|
||||
/**
|
||||
* Get random enemy
|
||||
* @param bl
|
||||
* @param ap
|
||||
* @return Found target (1) or not found (0)
|
||||
*/
|
||||
static int battle_getenemy_sub(struct block_list *bl, va_list ap)
|
||||
{
|
||||
struct block_list **bl_list;
|
||||
struct block_list *target;
|
||||
int *c;
|
||||
@ -143,8 +171,16 @@ static int battle_getenemy_sub(struct block_list *bl, va_list ap) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Picks a random enemy of the given type (BL_PC, BL_CHAR, etc) within the range given. [Skotlex]
|
||||
struct block_list* battle_getenemy(struct block_list *target, int type, int range) {
|
||||
/**
|
||||
* Returns list of enemies within given range
|
||||
* @param target
|
||||
* @param type
|
||||
* @param range
|
||||
* @return Target list
|
||||
* @author [Skotlex]
|
||||
*/
|
||||
struct block_list* battle_getenemy(struct block_list *target, int type, int range)
|
||||
{
|
||||
struct block_list *bl_list[24];
|
||||
int c = 0;
|
||||
|
||||
@ -159,7 +195,15 @@ struct block_list* battle_getenemy(struct block_list *target, int type, int rang
|
||||
|
||||
return bl_list[rnd()%c];
|
||||
}
|
||||
static int battle_getenemyarea_sub(struct block_list *bl, va_list ap) {
|
||||
|
||||
/**
|
||||
* Get random enemy within area
|
||||
* @param bl
|
||||
* @param ap
|
||||
* @return Found target (1) or not found (0)
|
||||
*/
|
||||
static int battle_getenemyarea_sub(struct block_list *bl, va_list ap)
|
||||
{
|
||||
struct block_list **bl_list, *src;
|
||||
int *c, ignore_id;
|
||||
|
||||
@ -185,8 +229,18 @@ static int battle_getenemyarea_sub(struct block_list *bl, va_list ap) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Pick a random enemy
|
||||
struct block_list* battle_getenemyarea(struct block_list *src, int x, int y, int range, int type, int ignore_id) {
|
||||
/**
|
||||
* Returns list of enemies within an area
|
||||
* @param src
|
||||
* @param x
|
||||
* @param y
|
||||
* @param range
|
||||
* @param type
|
||||
* @param ignore_id
|
||||
* @return Target list
|
||||
*/
|
||||
struct block_list* battle_getenemyarea(struct block_list *src, int x, int y, int range, int type, int ignore_id)
|
||||
{
|
||||
struct block_list *bl_list[24];
|
||||
int c = 0;
|
||||
|
||||
@ -201,7 +255,7 @@ struct block_list* battle_getenemyarea(struct block_list *src, int x, int y, int
|
||||
return bl_list[rnd()%c];
|
||||
}
|
||||
|
||||
// Damage delayed info
|
||||
/// Damage Delayed Structure
|
||||
struct delay_damage {
|
||||
int src_id;
|
||||
int target_id;
|
||||
@ -216,7 +270,8 @@ struct delay_damage {
|
||||
enum bl_type src_type;
|
||||
};
|
||||
|
||||
int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr_t data) {
|
||||
int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr_t data)
|
||||
{
|
||||
struct delay_damage *dat = (struct delay_damage *)data;
|
||||
|
||||
if ( dat ) {
|
||||
@ -246,10 +301,7 @@ int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr_t data) {
|
||||
if( dat->dmg_lv > ATK_BLOCK && dat->attack_type )
|
||||
skill_counter_additional_effect(src,target,dat->skill_id,dat->skill_lv,dat->attack_type,tick);
|
||||
map_freeblock_unlock();
|
||||
} else if( !src && dat->skill_id == CR_REFLECTSHIELD ) {
|
||||
/**
|
||||
* it was monster reflected damage, and the monster died, we pass the damage to the character as expected
|
||||
**/
|
||||
} else if( !src && dat->skill_id == CR_REFLECTSHIELD ) { // it was monster reflected damage, and the monster died, we pass the damage to the character as expected
|
||||
map_freeblock_lock();
|
||||
status_fix_damage(target, target, dat->damage, dat->delay);
|
||||
map_freeblock_unlock();
|
||||
@ -310,11 +362,11 @@ int battle_delay_damage(unsigned int tick, int amotion, struct block_list *src,
|
||||
}
|
||||
|
||||
/**
|
||||
* Get attribute ratio
|
||||
* @param atk_elem Attack element enum e_element
|
||||
* @param def_type Defense element enum e_element
|
||||
* @param def_lv Element level 1 ~ MAX_ELE_LEVEL
|
||||
*/
|
||||
* Get attribute ratio
|
||||
* @param atk_elem Attack element enum e_element
|
||||
* @param def_type Defense element enum e_element
|
||||
* @param def_lv Element level 1 ~ MAX_ELE_LEVEL
|
||||
*/
|
||||
int battle_attr_ratio(int atk_elem,int def_type, int def_lv) {
|
||||
if (!CHK_ELEMENT(atk_elem) || !CHK_ELEMENT(def_type) || !CHK_ELEMENT_LEVEL(def_lv))
|
||||
return 100;
|
||||
@ -322,14 +374,21 @@ int battle_attr_ratio(int atk_elem,int def_type, int def_lv) {
|
||||
return attr_fix_table[def_lv-1][atk_elem][def_type];
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* Does attribute fix modifiers.
|
||||
* Added passing of the chars so that the status changes can affect it. [Skotlex]
|
||||
* Note: Passing src/target == NULL is perfectly valid, it skips SC_ checks.
|
||||
*------------------------------------------*/
|
||||
* @param src
|
||||
* @param target
|
||||
* @param damage
|
||||
* @param atk_elem
|
||||
* @param def_type
|
||||
* @param def_lv
|
||||
* @return damage
|
||||
*/
|
||||
int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 damage,int atk_elem,int def_type, int def_lv)
|
||||
{
|
||||
struct status_change *sc=NULL, *tsc=NULL;
|
||||
struct status_change *sc = NULL, *tsc = NULL;
|
||||
int ratio;
|
||||
|
||||
if (src) sc = status_get_sc(src);
|
||||
@ -339,7 +398,7 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d
|
||||
atk_elem = rnd()%ELE_ALL;
|
||||
|
||||
if (!CHK_ELEMENT(def_type) || !CHK_ELEMENT_LEVEL(def_lv)) {
|
||||
ShowError("battle_attr_fix: unknown attr type: atk=%d def_type=%d def_lv=%d\n",atk_elem,def_type,def_lv);
|
||||
ShowError("battle_attr_fix: unknown attribute type: atk=%d def_type=%d def_lv=%d\n",atk_elem,def_type,def_lv);
|
||||
return damage;
|
||||
}
|
||||
|
||||
@ -360,6 +419,7 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( target && target->type == BL_SKILL ) {
|
||||
if( atk_elem == ELE_FIRE && battle_getcurrentskill(target) == GN_WALLOFTHORN ) {
|
||||
struct skill_unit *su = (struct skill_unit*)target;
|
||||
@ -381,7 +441,6 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( tsc && tsc->count ) { //increase dmg by target status
|
||||
switch(atk_elem) {
|
||||
case ELE_FIRE:
|
||||
@ -424,9 +483,19 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d
|
||||
return (int64)damage*ratio/100;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* Calculates card bonuses damage adjustments.
|
||||
*------------------------------------------*/
|
||||
* @param attack_type
|
||||
* @param src
|
||||
* @param target
|
||||
* @param nk
|
||||
* @param s_ele
|
||||
* @param s_ele_
|
||||
* @param damage
|
||||
* @param left
|
||||
* @param flag
|
||||
* @return damage
|
||||
*/
|
||||
int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_list *target, int nk, int s_ele, int s_ele_, int64 damage, int left, int flag){
|
||||
struct map_session_data *sd, *tsd;
|
||||
short cardfix = 1000, t_class, s_class, s_race2, t_race2;
|
||||
@ -718,11 +787,18 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
|
||||
return (int)(damage - original_damage);
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* Check damage through status.
|
||||
* ATK may be MISS, BLOCKED FAIL, reduc, increase, end status...
|
||||
* ATK may be MISS, BLOCKED FAIL, reduc, increase, end status.
|
||||
* After this we apply bg/gvg reduction
|
||||
*------------------------------------------*/
|
||||
* @param src
|
||||
* @param bl
|
||||
* @param d
|
||||
* @param damage
|
||||
* @param skill_id
|
||||
* @param skill_lv
|
||||
* @return damage
|
||||
*/
|
||||
int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damage *d,int64 damage,uint16 skill_id,uint16 skill_lv)
|
||||
{
|
||||
struct map_session_data *sd = NULL;
|
||||
@ -764,10 +840,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
|
||||
if (skill_id == PA_PRESSURE)
|
||||
return damage; //This skill bypass everything else.
|
||||
|
||||
if( sc && sc->count ) {
|
||||
/**
|
||||
* SC_* that reduce damage to 0.
|
||||
**/
|
||||
if( sc && sc->count ) { // SC_* that reduce damage to 0.
|
||||
if( sc->data[SC_BASILICA] && !(status_get_mode(src)&MD_BOSS) ) {
|
||||
d->dmg_lv = ATK_BLOCK;
|
||||
return 0;
|
||||
@ -1010,9 +1083,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
|
||||
status_change_end(bl,SC_VOICEOFSIREN,INVALID_TIMER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Damage reductions
|
||||
**/
|
||||
// Damage reductions
|
||||
// Assumptio doubles the def & mdef on RE mode, otherwise gives a reduction on the final damage. [Igniz]
|
||||
#ifndef RENEWAL
|
||||
if( sc->data[SC_ASSUMPTIO] ) {
|
||||
@ -1286,9 +1357,14 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
|
||||
return damage;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* Calculates BG related damage adjustments.
|
||||
*------------------------------------------
|
||||
* @param src
|
||||
* @param bl
|
||||
* @param damage
|
||||
* @param skill_id
|
||||
* @param flag
|
||||
* @return damage
|
||||
* Credits:
|
||||
* Original coder Skoltex
|
||||
* Initial refactoring by Baalberith
|
||||
@ -1326,6 +1402,14 @@ int64 battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int64
|
||||
return damage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether target can be hit
|
||||
* @param src
|
||||
* @param bl
|
||||
* @param skill_id
|
||||
* @param flag
|
||||
* @return Can be hit (true) or can't be hit (false)
|
||||
*/
|
||||
bool battle_can_hit_gvg_target(struct block_list *src,struct block_list *bl,uint16 skill_id,int flag)
|
||||
{
|
||||
struct mob_data* md = BL_CAST(BL_MOB, bl);
|
||||
@ -1347,9 +1431,15 @@ bool battle_can_hit_gvg_target(struct block_list *src,struct block_list *bl,uint
|
||||
return true;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* Calculates GVG related damage adjustments.
|
||||
*------------------------------------------*/
|
||||
* @param src
|
||||
* @param bl
|
||||
* @param damage
|
||||
* @param skill_id
|
||||
* @param flag
|
||||
* @return damage
|
||||
*/
|
||||
int64 battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int64 damage,uint16 skill_id,int flag)
|
||||
{
|
||||
if (!damage) //No reductions to make.
|
||||
@ -1381,9 +1471,13 @@ int64 battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int64
|
||||
return damage;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* HP/SP drain calculation
|
||||
*------------------------------------------*/
|
||||
* @param damage
|
||||
* @param rate
|
||||
* @param per
|
||||
* @return diff
|
||||
*/
|
||||
static int battle_calc_drain(int64 damage, int rate, int per)
|
||||
{
|
||||
int64 diff = 0;
|
||||
@ -1400,9 +1494,14 @@ static int battle_calc_drain(int64 damage, int rate, int per)
|
||||
return (int)diff;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
/**
|
||||
* Passive skill damage increases
|
||||
*------------------------------------------*/
|
||||
* @param sd
|
||||
* @param target
|
||||
* @param dmg
|
||||
* @param type
|
||||
* @return damage
|
||||
*/
|
||||
int64 battle_addmastery(struct map_session_data *sd,struct block_list *target,int64 dmg,int type)
|
||||
{
|
||||
int64 damage;
|
||||
@ -1517,7 +1616,6 @@ int64 battle_addmastery(struct map_session_data *sd,struct block_list *target,in
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if(sd->sc.data[SC_GN_CARTBOOST]) // cart boost adds mastery type damage
|
||||
damage += 10*sd->sc.data[SC_GN_CARTBOOST]->val1;
|
||||
|
||||
@ -1750,11 +1848,12 @@ static int battle_blewcount_bonus(struct map_session_data *sd, uint16 skill_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Damage calculation for adjusting skill damage
|
||||
/**
|
||||
* Damage calculation for adjusting skill damage
|
||||
* @param caster Applied caster type for damage skill
|
||||
* @param type BL_Type of attacker
|
||||
* @author [Lilith] for the first release of this, [Cydh]
|
||||
**/
|
||||
*/
|
||||
#ifdef ADJUST_SKILL_DAMAGE
|
||||
static bool battle_skill_damage_iscaster(uint8 caster, enum bl_type src_type) {
|
||||
if (caster == 0)
|
||||
@ -1771,12 +1870,13 @@ static bool battle_skill_damage_iscaster(uint8 caster, enum bl_type src_type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Gets skill damage rate from a skill (based on skill_damage_db.txt)
|
||||
* @param src
|
||||
* @param target
|
||||
* @param skill_id
|
||||
* @return Skill damage rate
|
||||
*/
|
||||
/**
|
||||
* Gets skill damage rate from a skill (based on skill_damage_db.txt)
|
||||
* @param src
|
||||
* @param target
|
||||
* @param skill_id
|
||||
* @return Skill damage rate
|
||||
*/
|
||||
static int battle_skill_damage_skill(struct block_list *src, struct block_list *target, uint16 skill_id) {
|
||||
uint16 idx = skill_get_index(skill_id), m = src->m;
|
||||
struct s_skill_damage *damage = NULL;
|
||||
@ -1813,12 +1913,13 @@ static int battle_skill_damage_skill(struct block_list *src, struct block_list *
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Gets skill damage rate from a skill (based on 'skill_damage' mapflag)
|
||||
* @param src
|
||||
* @param target
|
||||
* @param skill_id
|
||||
* @return Skill damage rate
|
||||
*/
|
||||
/**
|
||||
* Gets skill damage rate from a skill (based on 'skill_damage' mapflag)
|
||||
* @param src
|
||||
* @param target
|
||||
* @param skill_id
|
||||
* @return Skill damage rate
|
||||
*/
|
||||
static int battle_skill_damage_map(struct block_list *src, struct block_list *target, uint16 skill_id) {
|
||||
int rate = 0;
|
||||
uint16 m = src->m;
|
||||
@ -1868,12 +1969,13 @@ static int battle_skill_damage_map(struct block_list *src, struct block_list *ta
|
||||
return rate;
|
||||
}
|
||||
|
||||
/** Check skill damage adjustment based on mapflags and skill_damage_db.txt for specified skill
|
||||
* @param src
|
||||
* @param target
|
||||
* @param skill_id
|
||||
* @return Total damage rate
|
||||
*/
|
||||
/**
|
||||
* Check skill damage adjustment based on mapflags and skill_damage_db.txt for specified skill
|
||||
* @param src
|
||||
* @param target
|
||||
* @param skill_id
|
||||
* @return Total damage rate
|
||||
*/
|
||||
static int battle_skill_damage(struct block_list *src, struct block_list *target, uint16 skill_id) {
|
||||
if (!target)
|
||||
return 0;
|
||||
@ -1919,7 +2021,7 @@ static bool target_has_infinite_defense(struct block_list *target, int skill_id)
|
||||
if(target->type == BL_SKILL) {
|
||||
TBL_SKILL *su = ((TBL_SKILL*)target);
|
||||
|
||||
if (su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD))
|
||||
if (su && su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD))
|
||||
return true;
|
||||
}
|
||||
return (tstatus->mode&MD_PLANT && skill_id != RA_CLUSTERBOMB
|
||||
@ -3419,9 +3521,6 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s
|
||||
skillratio = 50 * skill_lv + 10 * (sd ? pc_checkskill(sd,KN_SPEARMASTERY) : 5);
|
||||
RE_LVL_DMOD(150); // Base level bonus.
|
||||
break;
|
||||
/**
|
||||
* GC Guilotine Cross
|
||||
**/
|
||||
case GC_CROSSIMPACT:
|
||||
skillratio += 900 + 100 * skill_lv;
|
||||
RE_LVL_DMOD(120);
|
||||
@ -3447,15 +3546,9 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s
|
||||
case GC_DARKCROW:
|
||||
skillratio += 100 * (skill_lv - 1);
|
||||
break;
|
||||
/**
|
||||
* Arch Bishop
|
||||
**/
|
||||
case AB_DUPLELIGHT_MELEE:
|
||||
skillratio += 10 * skill_lv;
|
||||
break;
|
||||
/**
|
||||
* Ranger
|
||||
**/
|
||||
case RA_ARROWSTORM:
|
||||
skillratio += 900 + 80 * skill_lv;
|
||||
RE_LVL_DMOD(100);
|
||||
@ -3484,9 +3577,6 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s
|
||||
case RA_SENSITIVEKEEN:
|
||||
skillratio += 50 * skill_lv;
|
||||
break;
|
||||
/**
|
||||
* Mechanic
|
||||
**/
|
||||
case NC_BOOSTKNUCKLE:
|
||||
skillratio += 100 + 100 * skill_lv + status_get_dex(src);
|
||||
RE_LVL_DMOD(120);
|
||||
@ -3862,9 +3952,6 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s
|
||||
skillratio += -100 + 100 * skill_lv + 3 * status_get_lv(src);
|
||||
skillratio = (skillratio * status_get_lv(src)) / 120;
|
||||
break;
|
||||
/**
|
||||
* Rebellion
|
||||
**/
|
||||
case RL_MASS_SPIRAL:
|
||||
// 200%:400%:600%:800%:1000%
|
||||
skillratio += -100 + (200 * skill_lv);
|
||||
@ -4291,10 +4378,10 @@ struct Damage battle_calc_defense_reduction(struct Damage wd, struct block_list
|
||||
|
||||
#ifdef RENEWAL
|
||||
/**
|
||||
* RE DEF Reduction
|
||||
* Damage = Attack * (4000+eDEF)/(4000+eDEF*10) - sDEF
|
||||
* Pierce defence gains 1 atk per def/2
|
||||
**/
|
||||
* RE DEF Reduction
|
||||
* Damage = Attack * (4000+eDEF)/(4000+eDEF*10) - sDEF
|
||||
* Pierce defence gains 1 atk per def/2
|
||||
*/
|
||||
if( def1 == -400 ) /* being hit by a gazillion units, -400 creates a division by 0 and subsequently crashes */
|
||||
def1 = -399;
|
||||
ATK_ADD2(wd.damage, wd.damage2,
|
||||
@ -4591,13 +4678,8 @@ struct Damage battle_calc_weapon_final_atk_modifiers(struct Damage wd, struct bl
|
||||
hp = 2*hp/100; //2% hp loss per hit
|
||||
status_zap(src, hp, 0);
|
||||
}
|
||||
/**
|
||||
* affecting non-skills
|
||||
**/
|
||||
// affecting non-skills
|
||||
if( !skill_id ) {
|
||||
/**
|
||||
* RK Enchant Blade
|
||||
**/
|
||||
if( sc->data[SC_ENCHANTBLADE] && sd && ( (is_attack_right_handed(src, skill_id) && sd->weapontype1) || (is_attack_left_handed(src, skill_id) && sd->weapontype2) ) ) {
|
||||
//[( ( Skill Lv x 20 ) + 100 ) x ( casterBaseLevel / 150 )] + casterInt
|
||||
ATK_ADD(wd.damage, wd.damage2, ( sc->data[SC_ENCHANTBLADE]->val1*20+100 ) * status_get_lv(src) / 150 + status_get_int(src) );
|
||||
@ -4728,10 +4810,10 @@ static struct Damage initialize_weapon_data(struct block_list *src, struct block
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if bl is devoted by someone
|
||||
* @param bl
|
||||
* @return 'd_bl' if devoted or NULL if not devoted
|
||||
*/
|
||||
* Check if bl is devoted by someone
|
||||
* @param bl
|
||||
* @return 'd_bl' if devoted or NULL if not devoted
|
||||
*/
|
||||
struct block_list *battle_check_devotion(struct block_list *bl) {
|
||||
struct block_list *d_bl = NULL;
|
||||
|
||||
@ -4743,7 +4825,7 @@ struct block_list *battle_check_devotion(struct block_list *bl) {
|
||||
return d_bl;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Check if we should reflect the damage and calculate it if so
|
||||
* @param attack_type : BL_WEAPON,BL_MAGIC or BL_MISC
|
||||
* @param wd : weapon damage
|
||||
@ -5216,9 +5298,10 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
|
||||
//Skill Range Criteria
|
||||
ad.flag |= battle_range_type(src, target, skill_id, skill_lv);
|
||||
flag.infdef=(tstatus->mode&MD_PLANT?1:0);
|
||||
if( target->type == BL_SKILL){
|
||||
if( target->type == BL_SKILL) {
|
||||
TBL_SKILL *su = (TBL_SKILL*)target;
|
||||
if( su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) )
|
||||
|
||||
if( su && su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) )
|
||||
flag.infdef = 1;
|
||||
}
|
||||
|
||||
@ -5257,9 +5340,6 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
|
||||
case AL_HEAL:
|
||||
case PR_BENEDICTIO:
|
||||
case PR_SANCTUARY:
|
||||
/**
|
||||
* Arch Bishop
|
||||
**/
|
||||
case AB_HIGHNESSHEAL:
|
||||
ad.damage = skill_calc_heal(src, target, skill_id, skill_lv, false);
|
||||
break;
|
||||
@ -5295,9 +5375,6 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
|
||||
case PF_SOULBURN:
|
||||
ad.damage = tstatus->sp * 2;
|
||||
break;
|
||||
/**
|
||||
* Arch Bishop
|
||||
**/
|
||||
case AB_RENOVATIO:
|
||||
ad.damage = status_get_lv(src) * 10 + sstatus->int_;
|
||||
break;
|
||||
@ -5360,9 +5437,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
|
||||
}
|
||||
break;
|
||||
case MG_THUNDERSTORM:
|
||||
/**
|
||||
* in Renewal Thunder Storm boost is 100% (in pre-re, 80%)
|
||||
**/
|
||||
// in Renewal Thunder Storm boost is 100% (in pre-re, 80%)
|
||||
#ifndef RENEWAL
|
||||
skillratio -= 20;
|
||||
#endif
|
||||
@ -5455,9 +5530,6 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
|
||||
skillratio += 20*skill_lv-20;
|
||||
break;
|
||||
#endif
|
||||
/**
|
||||
* Arch Bishop
|
||||
**/
|
||||
case AB_JUDEX:
|
||||
skillratio += 200 + 20 * skill_lv;
|
||||
RE_LVL_DMOD(100);
|
||||
@ -5469,9 +5541,6 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
|
||||
case AB_DUPLELIGHT_MAGIC:
|
||||
skillratio += 100 + 20 * skill_lv;
|
||||
break;
|
||||
/**
|
||||
* Warlock
|
||||
**/
|
||||
case WL_SOULEXPANSION:
|
||||
skillratio += 300 + 100 * skill_lv + status_get_int(src);
|
||||
RE_LVL_DMOD(100);
|
||||
@ -5793,7 +5862,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
|
||||
/**
|
||||
* RE MDEF Reduction
|
||||
* Damage = Magic Attack * (1000+eMDEF)/(1000+eMDEF) - sMDEF
|
||||
**/
|
||||
*/
|
||||
if (mdef < -99)
|
||||
mdef = -99; // Avoid divide by 0
|
||||
|
||||
@ -6231,7 +6300,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
|
||||
|
||||
if(md.damage < 0)
|
||||
md.damage = 0;
|
||||
else if(md.damage && tstatus->mode&MD_PLANT){
|
||||
else if(md.damage && tstatus->mode&MD_PLANT) {
|
||||
switch(skill_id){
|
||||
case NJ_ISSEN: // Final Strike will MISS on "plant"-type mobs [helvetica]
|
||||
md.damage = 0;
|
||||
@ -6248,9 +6317,10 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
|
||||
default:
|
||||
md.damage = 1;
|
||||
}
|
||||
}else if( target->type == BL_SKILL ){
|
||||
} else if( target->type == BL_SKILL ) {
|
||||
TBL_SKILL *su = (TBL_SKILL*)target;
|
||||
if( su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) )
|
||||
|
||||
if( su && su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) )
|
||||
md.damage = 1;
|
||||
}
|
||||
|
||||
@ -6678,7 +6748,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
|
||||
/**
|
||||
* We need to calculate the DMG before the hp reduction, because it can kill the source.
|
||||
* For further information: bugreport:4950
|
||||
**/
|
||||
*/
|
||||
ret_val = (damage_lv)skill_attack(BF_WEAPON,src,src,target,PA_SACRIFICE,skill_lv,tick,0);
|
||||
|
||||
status_zap(src, sstatus->max_hp*9/100, 0);//Damage to self is always 9%
|
||||
@ -6762,10 +6832,10 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
|
||||
|
||||
if (sd && sd->bonus.splash_range > 0 && damage > 0)
|
||||
skill_castend_damage_id(src, target, 0, 1, tick, 0);
|
||||
if ( target->type == BL_SKILL && damage > 0 ){
|
||||
if ( target->type == BL_SKILL && damage > 0 ) {
|
||||
TBL_SKILL *su = (TBL_SKILL*)target;
|
||||
|
||||
if (su->group) {
|
||||
if (su && su->group) {
|
||||
if (su->group->skill_id == HT_BLASTMINE)
|
||||
skill_blown(src, target, 3, -1, 0);
|
||||
if (su->group->skill_id == GN_WALLOFTHORN) {
|
||||
@ -7077,9 +7147,8 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
|
||||
case BL_SKILL:
|
||||
{
|
||||
TBL_SKILL *su = (TBL_SKILL*)target;
|
||||
if( !su->group )
|
||||
return 0;
|
||||
if( skill_get_inf2(su->group->skill_id)&INF2_TRAP ) { //Only a few skills can target traps...
|
||||
|
||||
if( su && su->group && skill_get_inf2(su->group->skill_id)&INF2_TRAP ) { //Only a few skills can target traps...
|
||||
switch( battle_getcurrentskill(src) ) {
|
||||
case RK_DRAGONBREATH:// it can only hit traps in pvp/gvg maps
|
||||
case RK_DRAGONBREATH_WATER:
|
||||
@ -7183,10 +7252,8 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
|
||||
break;
|
||||
case BL_SKILL: {
|
||||
struct skill_unit *su = (struct skill_unit *)src;
|
||||
if (!su->group)
|
||||
return 0;
|
||||
|
||||
if (su->group->src_id == target->id) {
|
||||
if (su && su->group && su->group->src_id == target->id) {
|
||||
int inf2 = skill_get_inf2(su->group->skill_id);
|
||||
if (inf2&INF2_NO_TARGET_SELF)
|
||||
return -1;
|
||||
@ -7754,9 +7821,7 @@ static const struct _battle_data {
|
||||
{ "bg_magic_attack_damage_rate", &battle_config.bg_magic_damage_rate, 60, 0, INT_MAX, },
|
||||
{ "bg_misc_attack_damage_rate", &battle_config.bg_misc_damage_rate, 60, 0, INT_MAX, },
|
||||
{ "bg_flee_penalty", &battle_config.bg_flee_penalty, 20, 0, INT_MAX, },
|
||||
/**
|
||||
* rAthena
|
||||
**/
|
||||
// rAthena
|
||||
{ "max_third_parameter", &battle_config.max_third_parameter, 135, 10, SHRT_MAX, },
|
||||
{ "max_baby_third_parameter", &battle_config.max_baby_third_parameter, 108, 10, SHRT_MAX, },
|
||||
{ "max_trans_parameter", &battle_config.max_trans_parameter, 99, 10, SHRT_MAX, },
|
||||
@ -7837,10 +7902,9 @@ static const struct _battle_data {
|
||||
{ "devotion_rdamage_skill_only", &battle_config.devotion_rdamage_skill_only, 1, 0, 1, },
|
||||
{ "max_extended_aspd", &battle_config.max_extended_aspd, 193, 100, 199, },
|
||||
};
|
||||
|
||||
#ifndef STATS_OPT_OUT
|
||||
/**
|
||||
* rAthena anonymous statistic usage report -- packet is built here, and sent to char server to report.
|
||||
**/
|
||||
// rAthena anonymous statistic usage report -- packet is built here, and sent to char server to report.
|
||||
void rAthena_report(char* date, char *time_c) {
|
||||
int i, rev = 0, bd_size = ARRAYLENGTH(battle_data);
|
||||
unsigned int config = 0;
|
||||
@ -7933,7 +7997,6 @@ void rAthena_report(char* date, char *time_c) {
|
||||
CREATE(buf, char, 6 + 12 + 9 + 24 + 4 + 4 + 4 + 4 + ( bd_size * ( BFLAG_LENGTH + 4 ) ) + 1 );
|
||||
|
||||
/* build packet */
|
||||
|
||||
WBUFW(buf,0) = 0x3000;
|
||||
WBUFW(buf,2) = 6 + 12 + 9 + 24 + 4 + 4 + 4 + 4 + ( bd_size * ( BFLAG_LENGTH + 4 ) );
|
||||
WBUFW(buf,4) = 0x9c;
|
||||
|
@ -27,16 +27,21 @@ static unsigned int bg_team_counter = 0; // Next bg_id
|
||||
|
||||
struct battleground_data* bg_team_search(int bg_id)
|
||||
{ // Search a BG Team using bg_id
|
||||
if( !bg_id ) return NULL;
|
||||
if( !bg_id )
|
||||
return NULL;
|
||||
|
||||
return (struct battleground_data *)idb_get(bg_team_db, bg_id);
|
||||
}
|
||||
|
||||
struct map_session_data* bg_getavailablesd(struct battleground_data *bg)
|
||||
{
|
||||
int i;
|
||||
|
||||
nullpo_retr(NULL, bg);
|
||||
|
||||
ARR_FIND(0, MAX_BG_MEMBERS, i, bg->members[i].sd != NULL);
|
||||
return( i < MAX_BG_MEMBERS ) ? bg->members[i].sd : NULL;
|
||||
|
||||
return ( i < MAX_BG_MEMBERS ) ? bg->members[i].sd : NULL;
|
||||
}
|
||||
|
||||
int bg_team_delete(int bg_id)
|
||||
@ -44,9 +49,10 @@ int bg_team_delete(int bg_id)
|
||||
int i;
|
||||
struct battleground_data *bg = bg_team_search(bg_id);
|
||||
|
||||
if( bg == NULL ) return 0;
|
||||
for( i = 0; i < MAX_BG_MEMBERS; i++ )
|
||||
{
|
||||
if( bg == NULL )
|
||||
return 0;
|
||||
|
||||
for( i = 0; i < MAX_BG_MEMBERS; i++ ) {
|
||||
struct map_session_data *sd;
|
||||
|
||||
if( (sd = bg->members[i].sd) == NULL )
|
||||
@ -55,7 +61,9 @@ int bg_team_delete(int bg_id)
|
||||
bg_send_dot_remove(sd);
|
||||
sd->bg_id = 0;
|
||||
}
|
||||
|
||||
idb_remove(bg_team_db, bg_id);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -63,7 +71,10 @@ int bg_team_warp(int bg_id, unsigned short mapindex, short x, short y)
|
||||
{ // Warps a Team
|
||||
int i;
|
||||
struct battleground_data *bg = bg_team_search(bg_id);
|
||||
if( bg == NULL ) return 0;
|
||||
|
||||
if( bg == NULL )
|
||||
return 0;
|
||||
|
||||
for( i = 0; i < MAX_BG_MEMBERS; i++ )
|
||||
if( bg->members[i].sd != NULL ) pc_setpos(bg->members[i].sd, mapindex, x, y, CLR_TELEPORT);
|
||||
return 1;
|
||||
@ -81,10 +92,12 @@ int bg_team_join(int bg_id, struct map_session_data *sd)
|
||||
int i;
|
||||
struct battleground_data *bg = bg_team_search(bg_id);
|
||||
|
||||
if( bg == NULL || sd == NULL || sd->bg_id ) return 0;
|
||||
if( bg == NULL || sd == NULL || sd->bg_id )
|
||||
return 0;
|
||||
|
||||
ARR_FIND(0, MAX_BG_MEMBERS, i, bg->members[i].sd == NULL);
|
||||
if( i == MAX_BG_MEMBERS ) return 0; // No free slots
|
||||
if( i == MAX_BG_MEMBERS )
|
||||
return 0; // No free slots
|
||||
|
||||
sd->bg_id = bg_id;
|
||||
bg->members[i].sd = sd;
|
||||
@ -94,8 +107,7 @@ int bg_team_join(int bg_id, struct map_session_data *sd)
|
||||
|
||||
guild_send_dot_remove(sd);
|
||||
|
||||
for( i = 0; i < MAX_BG_MEMBERS; i++ )
|
||||
{
|
||||
for( i = 0; i < MAX_BG_MEMBERS; i++ ) {
|
||||
struct map_session_data *pl_sd;
|
||||
|
||||
if( (pl_sd = bg->members[i].sd) != NULL && pl_sd != sd )
|
||||
@ -126,12 +138,14 @@ int bg_team_leave(struct map_session_data *sd, int flag)
|
||||
ARR_FIND(0, MAX_BG_MEMBERS, i, bg->members[i].sd == sd);
|
||||
if( i < MAX_BG_MEMBERS ) // Removes member from BG
|
||||
memset(&bg->members[i], 0, sizeof(bg->members[0]));
|
||||
|
||||
bg->count--;
|
||||
|
||||
if( flag )
|
||||
sprintf(output, "Server : %s has quit the game...", sd->status.name);
|
||||
else
|
||||
sprintf(output, "Server : %s is leaving the battlefield...", sd->status.name);
|
||||
|
||||
clif_bg_message(bg, 0, "Server", output, strlen(output) + 1);
|
||||
|
||||
if( bg->logout_event[0] && flag )
|
||||
@ -143,10 +157,13 @@ int bg_team_leave(struct map_session_data *sd, int flag)
|
||||
int bg_member_respawn(struct map_session_data *sd)
|
||||
{ // Respawn after killed
|
||||
struct battleground_data *bg;
|
||||
|
||||
if( sd == NULL || !pc_isdead(sd) || !sd->bg_id || (bg = bg_team_search(sd->bg_id)) == NULL )
|
||||
return 0;
|
||||
|
||||
if( bg->mapindex == 0 )
|
||||
return 0; // Respawn not handled by Core
|
||||
|
||||
pc_setpos(sd, bg->mapindex, bg->x, bg->y, CLR_OUTSIGHT);
|
||||
status_revive(&sd->bl, 1, 100);
|
||||
|
||||
@ -176,20 +193,20 @@ int bg_create(unsigned short mapindex, short rx, short ry, const char *ev, const
|
||||
int bg_team_get_id(struct block_list *bl)
|
||||
{
|
||||
nullpo_ret(bl);
|
||||
switch( bl->type )
|
||||
{
|
||||
switch( bl->type ) {
|
||||
case BL_PC:
|
||||
return ((TBL_PC*)bl)->bg_id;
|
||||
case BL_PET:
|
||||
if( ((TBL_PET*)bl)->master )
|
||||
return ((TBL_PET*)bl)->master->bg_id;
|
||||
break;
|
||||
case BL_MOB:
|
||||
{
|
||||
case BL_MOB: {
|
||||
struct map_session_data *msd;
|
||||
struct mob_data *md = (TBL_MOB*)bl;
|
||||
|
||||
if( md->special_state.ai && (msd = map_id2sd(md->master_id)) != NULL )
|
||||
return msd->bg_id;
|
||||
|
||||
return md->bg_id;
|
||||
}
|
||||
case BL_HOM:
|
||||
@ -212,9 +229,12 @@ int bg_send_message(struct map_session_data *sd, const char *mes, int len)
|
||||
struct battleground_data *bg;
|
||||
|
||||
nullpo_ret(sd);
|
||||
|
||||
if( sd->bg_id == 0 || (bg = bg_team_search(sd->bg_id)) == NULL )
|
||||
return 0;
|
||||
|
||||
clif_bg_message(bg, sd->bl.id, sd->status.name, mes, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -226,24 +246,27 @@ int bg_send_xy_timer_sub(DBKey key, DBData *data, va_list ap)
|
||||
struct battleground_data *bg = db_data2ptr(data);
|
||||
struct map_session_data *sd;
|
||||
int i;
|
||||
|
||||
nullpo_ret(bg);
|
||||
for( i = 0; i < MAX_BG_MEMBERS; i++ )
|
||||
{
|
||||
|
||||
for( i = 0; i < MAX_BG_MEMBERS; i++ ) {
|
||||
if( (sd = bg->members[i].sd) == NULL )
|
||||
continue;
|
||||
if( sd->bl.x != bg->members[i].x || sd->bl.y != bg->members[i].y )
|
||||
{ // xy update
|
||||
|
||||
if( sd->bl.x != bg->members[i].x || sd->bl.y != bg->members[i].y ) { // xy update
|
||||
bg->members[i].x = sd->bl.x;
|
||||
bg->members[i].y = sd->bl.y;
|
||||
clif_bg_xy(sd);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bg_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data)
|
||||
{
|
||||
bg_team_db->foreach(bg_team_db, bg_send_xy_timer_sub, tick);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -496,11 +496,14 @@ int channel_display_list(struct map_session_data *sd, char *options){
|
||||
clif_displaymessage(sd->fd, msg_txt(sd,1476)); // You have not joined any channels.
|
||||
else {
|
||||
unsigned char k;
|
||||
struct Channel *channel;
|
||||
for(k=0; k<sd->channel_count; k++){
|
||||
|
||||
for(k = 0; k < sd->channel_count; k++) {
|
||||
char output[128];
|
||||
struct Channel *channel;
|
||||
|
||||
if (!(channel = sd->channels[k]))
|
||||
continue;
|
||||
|
||||
sprintf(output, msg_txt(sd,1409), channel->name, db_size(channel->users));// - #%s (%d users)
|
||||
clif_displaymessage(sd->fd, output);
|
||||
}
|
||||
|
@ -17373,7 +17373,8 @@ void clif_crimson_marker(struct map_session_data *sd, struct block_list *bl, boo
|
||||
//void clif_broadcast_obtain_special_item() {}
|
||||
|
||||
#ifdef DUMP_UNKNOWN_PACKET
|
||||
void DumpUnknow(int fd,TBL_PC *sd,int cmd,int packet_len){
|
||||
void DumpUnknown(int fd,TBL_PC *sd,int cmd,int packet_len)
|
||||
{
|
||||
const char* packet_txt = "save/packet.txt";
|
||||
FILE* fp;
|
||||
time_t time_server;
|
||||
@ -17527,7 +17528,7 @@ static int clif_parse(int fd)
|
||||
packet_db[packet_ver][cmd].func(fd, sd);
|
||||
}
|
||||
#ifdef DUMP_UNKNOWN_PACKET
|
||||
else DumpUnknow(fd,sd,cmd,packet_len);
|
||||
else DumpUnknown(fd,sd,cmd,packet_len);
|
||||
#endif
|
||||
RFIFOSKIP(fd, packet_len);
|
||||
}; // main loop end
|
||||
@ -17540,7 +17541,6 @@ static int clif_parse(int fd)
|
||||
*------------------------------------------*/
|
||||
void packetdb_readdb(void)
|
||||
{
|
||||
FILE *fp;
|
||||
char line[1024];
|
||||
int cmd,i,j;
|
||||
int max_cmd=-1;
|
||||
@ -18038,13 +18038,14 @@ void packetdb_readdb(void)
|
||||
packet_len(i) = packet_len_table[i];
|
||||
|
||||
clif_config.packet_db_ver = MAX_PACKET_VER;
|
||||
for(f = 0; f < ARRAYLENGTH(filename); f++){
|
||||
int ln=0;
|
||||
for(f = 0; f < ARRAYLENGTH(filename); f++) {
|
||||
FILE *fp;
|
||||
int ln = 0;
|
||||
int entries = 0;
|
||||
char *str[64],*p,*str2[64],*p2;
|
||||
char *str[64], *p, *str2[64], *p2;
|
||||
|
||||
sprintf(line, "%s/%s", db_path, filename[f]);
|
||||
if( (fp = fopen(line,"r")) == NULL ){
|
||||
if( (fp = fopen(line,"r")) == NULL ) {
|
||||
if (f == 0) {
|
||||
ShowFatalError("Can't read %s\n", line);
|
||||
exit(EXIT_FAILURE);
|
||||
|
405
src/map/party.c
405
src/map/party.c
File diff suppressed because it is too large
Load Diff
@ -254,7 +254,7 @@ static int add_path(struct node_heap *heap, struct path_node *tp, int16 x, int16
|
||||
*------------------------------------------*/
|
||||
bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int flag, cell_chk cell)
|
||||
{
|
||||
register int i, j, x, y, dx = 0, dy = 0;
|
||||
register int i, x, y, dx = 0, dy = 0;
|
||||
struct map_data *md;
|
||||
struct walkpath_data s_wpd;
|
||||
|
||||
@ -263,6 +263,7 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x
|
||||
|
||||
if (!map[m].cell)
|
||||
return false;
|
||||
|
||||
md = &map[m];
|
||||
|
||||
#ifdef CELL_NOSTACK
|
||||
@ -288,8 +289,7 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x
|
||||
x = x0; // Current position = starting cell
|
||||
y = y0;
|
||||
i = 0;
|
||||
while( i < ARRAYLENGTH(wpd->path) )
|
||||
{
|
||||
while( i < ARRAYLENGTH(wpd->path) ) {
|
||||
wpd->path[i] = walk_choices[-dy + 1][dx + 1];
|
||||
i++;
|
||||
|
||||
@ -305,16 +305,14 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x
|
||||
break; // obstacle = failure
|
||||
}
|
||||
|
||||
if( x == x1 && y == y1 )
|
||||
{ // easy path successful.
|
||||
if( x == x1 && y == y1 ) { // easy path successful.
|
||||
wpd->path_len = i;
|
||||
wpd->path_pos = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false; // easy path unsuccessful
|
||||
}
|
||||
else { // !(flag&1)
|
||||
} else { // !(flag&1)
|
||||
// A* (A-star) pathfinding
|
||||
// We always use A* for finding walkpaths because it is what game client uses.
|
||||
// Easy pathfinding cuts corners of non-walkable cells, but client always walks around it.
|
||||
@ -329,6 +327,8 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x
|
||||
int xs = md->xs - 1;
|
||||
int ys = md->ys - 1;
|
||||
int len = 0;
|
||||
int j;
|
||||
|
||||
memset(tp, 0, sizeof(tp));
|
||||
|
||||
// Start node
|
||||
@ -341,8 +341,8 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x
|
||||
tp[i].flag = SET_OPEN;
|
||||
|
||||
heap_push_node(&open_set, &tp[i]); // Put start node to 'open' set
|
||||
for(;;)
|
||||
{
|
||||
|
||||
for(;;) {
|
||||
int e = 0; // error flag
|
||||
|
||||
// Saves allowed directions for the current cell. Diagonal directions
|
||||
@ -407,18 +407,19 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x
|
||||
}
|
||||
|
||||
for (it = current; it->parent != NULL; it = it->parent, len++);
|
||||
if (len > sizeof(wpd->path)) {
|
||||
if (len > sizeof(wpd->path))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Recreate path
|
||||
wpd->path_len = len;
|
||||
wpd->path_pos = 0;
|
||||
|
||||
for (it = current, j = len-1; j >= 0; it = it->parent, j--) {
|
||||
dx = it->x - it->parent->x;
|
||||
dy = it->y - it->parent->y;
|
||||
wpd->path[j] = walk_choices[-dy + 1][dx + 1];
|
||||
}
|
||||
|
||||
return true;
|
||||
} // A* end
|
||||
|
||||
|
@ -10870,7 +10870,7 @@ int pc_autotrade_timer(int tid, unsigned int tick, int id, intptr_t data) {
|
||||
buyingstore_reopen(sd);
|
||||
vending_reopen(sd);
|
||||
|
||||
if (sd && !sd->vender_id && !sd->buyer_id) {
|
||||
if (!sd->vender_id && !sd->buyer_id) {
|
||||
sd->state.autotrade = 0;
|
||||
map_quit(sd);
|
||||
}
|
||||
|
@ -38,9 +38,11 @@
|
||||
* @param quest_id ID to lookup
|
||||
* @return Quest entry (equals to &quest_dummy if the ID is invalid)
|
||||
*/
|
||||
struct quest_db *quest_db(int quest_id) {
|
||||
struct quest_db *quest_db(int quest_id)
|
||||
{
|
||||
if( quest_id < 0 || quest_id > MAX_QUEST_DB || quest_db_data[quest_id] == NULL )
|
||||
return &quest_dummy;
|
||||
|
||||
return quest_db_data[quest_id];
|
||||
}
|
||||
|
||||
@ -50,7 +52,8 @@ struct quest_db *quest_db(int quest_id) {
|
||||
* @param sd Player's data
|
||||
* @return 0 in case of success, nonzero otherwise (i.e. the player has no quests)
|
||||
*/
|
||||
int quest_pc_login(TBL_PC *sd) {
|
||||
int quest_pc_login(TBL_PC *sd)
|
||||
{
|
||||
int i;
|
||||
|
||||
if( sd->avail_quests == 0 )
|
||||
@ -75,7 +78,8 @@ int quest_pc_login(TBL_PC *sd) {
|
||||
* @param quest_id ID of the quest to add.
|
||||
* @return 0 in case of success, nonzero otherwise
|
||||
*/
|
||||
int quest_add(TBL_PC *sd, int quest_id) {
|
||||
int quest_add(TBL_PC *sd, int quest_id)
|
||||
{
|
||||
int n;
|
||||
struct quest_db *qi = quest_db(quest_id);
|
||||
|
||||
@ -125,7 +129,8 @@ int quest_add(TBL_PC *sd, int quest_id) {
|
||||
* @param qid2 New quest to add
|
||||
* @return 0 in case of success, nonzero otherwise
|
||||
*/
|
||||
int quest_change(TBL_PC *sd, int qid1, int qid2) {
|
||||
int quest_change(TBL_PC *sd, int qid1, int qid2)
|
||||
{
|
||||
int i;
|
||||
struct quest_db *qi = quest_db(qid2);
|
||||
|
||||
@ -152,8 +157,10 @@ int quest_change(TBL_PC *sd, int qid1, int qid2) {
|
||||
|
||||
memset(&sd->quest_log[i], 0, sizeof(struct quest));
|
||||
sd->quest_log[i].quest_id = qi->id;
|
||||
|
||||
if( qi->time )
|
||||
sd->quest_log[i].time = (unsigned int)(time(NULL) + qi->time);
|
||||
|
||||
sd->quest_log[i].state = Q_ACTIVE;
|
||||
|
||||
sd->save_quest = true;
|
||||
@ -175,7 +182,8 @@ int quest_change(TBL_PC *sd, int qid1, int qid2) {
|
||||
* @param quest_id ID of the quest to remove
|
||||
* @return 0 in case of success, nonzero otherwise
|
||||
*/
|
||||
int quest_delete(TBL_PC *sd, int quest_id) {
|
||||
int quest_delete(TBL_PC *sd, int quest_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
//Search for quest
|
||||
@ -184,15 +192,19 @@ int quest_delete(TBL_PC *sd, int quest_id) {
|
||||
ShowError("quest_delete: Character %d doesn't have quest %d.\n", sd->status.char_id, quest_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( sd->quest_log[i].state != Q_COMPLETE )
|
||||
sd->avail_quests--;
|
||||
|
||||
if( i < --sd->num_quests ) //Compact the array
|
||||
memmove(&sd->quest_log[i], &sd->quest_log[i + 1], sizeof(struct quest) * (sd->num_quests - i));
|
||||
|
||||
if( sd->num_quests == 0 ) {
|
||||
aFree(sd->quest_log);
|
||||
sd->quest_log = NULL;
|
||||
} else
|
||||
RECREATE(sd->quest_log, struct quest, sd->num_quests);
|
||||
|
||||
sd->save_quest = true;
|
||||
|
||||
clif_quest_delete(sd, quest_id);
|
||||
@ -211,7 +223,8 @@ int quest_delete(TBL_PC *sd, int quest_id) {
|
||||
* int Party ID
|
||||
* int Mob ID
|
||||
*/
|
||||
int quest_update_objective_sub(struct block_list *bl, va_list ap) {
|
||||
int quest_update_objective_sub(struct block_list *bl, va_list ap)
|
||||
{
|
||||
struct map_session_data *sd;
|
||||
int mob, party;
|
||||
|
||||
@ -237,7 +250,8 @@ int quest_update_objective_sub(struct block_list *bl, va_list ap) {
|
||||
* @param sd Character's data
|
||||
* @param mob_id Monster ID
|
||||
*/
|
||||
void quest_update_objective(TBL_PC *sd, int mob) {
|
||||
void quest_update_objective(TBL_PC *sd, int mob)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for( i = 0; i < sd->avail_quests; i++ ) {
|
||||
@ -268,7 +282,8 @@ void quest_update_objective(TBL_PC *sd, int mob) {
|
||||
* @param qs New quest state
|
||||
* @return 0 in case of success, nonzero otherwise
|
||||
*/
|
||||
int quest_update_status(TBL_PC *sd, int quest_id, enum quest_state status) {
|
||||
int quest_update_status(TBL_PC *sd, int quest_id, enum quest_state status)
|
||||
{
|
||||
int i;
|
||||
|
||||
ARR_FIND(0, sd->avail_quests, i, sd->quest_log[i].quest_id == quest_id);
|
||||
@ -317,7 +332,8 @@ int quest_update_status(TBL_PC *sd, int quest_id, enum quest_state status) {
|
||||
* 1 if the quest's timeout has expired
|
||||
* 0 otherwise
|
||||
*/
|
||||
int quest_check(TBL_PC *sd, int quest_id, enum quest_check_type type) {
|
||||
int quest_check(TBL_PC *sd, int quest_id, enum quest_check_type type)
|
||||
{
|
||||
int i;
|
||||
|
||||
ARR_FIND(0, sd->num_quests, i, sd->quest_log[i].quest_id == quest_id);
|
||||
@ -354,7 +370,8 @@ int quest_check(TBL_PC *sd, int quest_id, enum quest_check_type type) {
|
||||
*
|
||||
* @return Number of loaded quests, or -1 if the file couldn't be read.
|
||||
*/
|
||||
int quest_read_db(void) {
|
||||
int quest_read_db(void)
|
||||
{
|
||||
const char* dbsubpath[] = {
|
||||
"",
|
||||
DBIMPORT"/",
|
||||
@ -373,11 +390,14 @@ int quest_read_db(void) {
|
||||
if( (fp = fopen(filename, "r")) == NULL ) {
|
||||
if (f == 0)
|
||||
ShowError("Can't read %s\n", filename);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
while( fgets(line, sizeof(line), fp) ) {
|
||||
if( line[0] == '/' && line[1] == '/' )
|
||||
continue;
|
||||
|
||||
memset(str, 0, sizeof(str));
|
||||
|
||||
for( i = 0, p = line; i < 8; i++ ) {
|
||||
@ -392,6 +412,7 @@ int quest_read_db(void) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if( str[0] == NULL )
|
||||
continue;
|
||||
|
||||
@ -422,6 +443,7 @@ int quest_read_db(void) {
|
||||
memcpy(quest_db_data[entry.id], &entry, sizeof(struct quest_db));
|
||||
count++;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename);
|
||||
}
|
||||
@ -437,7 +459,8 @@ int quest_read_db(void) {
|
||||
* @see map_foreachpc
|
||||
* @param ap Ignored
|
||||
*/
|
||||
int quest_reload_check_sub(struct map_session_data *sd, va_list ap) {
|
||||
int quest_reload_check_sub(struct map_session_data *sd, va_list ap)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
nullpo_ret(sd);
|
||||
@ -451,12 +474,15 @@ int quest_reload_check_sub(struct map_session_data *sd, va_list ap) {
|
||||
clif_quest_delete(sd, sd->quest_log[i].quest_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if( i != j ) {
|
||||
//Move entries if there's a gap to fill
|
||||
memcpy(&sd->quest_log[j], &sd->quest_log[i], sizeof(struct quest));
|
||||
}
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
sd->num_quests = j;
|
||||
ARR_FIND(0, sd->num_quests, i, sd->quest_log[i].state == Q_COMPLETE);
|
||||
sd->avail_quests = i;
|
||||
@ -467,7 +493,8 @@ int quest_reload_check_sub(struct map_session_data *sd, va_list ap) {
|
||||
/**
|
||||
* Clears the quest database for shutdown or reload.
|
||||
*/
|
||||
void quest_clear_db(void) {
|
||||
void quest_clear_db(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < MAX_QUEST_DB; i++ ) {
|
||||
@ -481,14 +508,16 @@ void quest_clear_db(void) {
|
||||
/**
|
||||
* Initializes the quest interface.
|
||||
*/
|
||||
void do_init_quest(void) {
|
||||
void do_init_quest(void)
|
||||
{
|
||||
quest_read_db();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalizes the quest interface before shutdown.
|
||||
*/
|
||||
void do_final_quest(void) {
|
||||
void do_final_quest(void)
|
||||
{
|
||||
memset(&quest_dummy, 0, sizeof(quest_dummy));
|
||||
|
||||
quest_clear_db();
|
||||
@ -497,7 +526,8 @@ void do_final_quest(void) {
|
||||
/**
|
||||
* Reloads the quest database.
|
||||
*/
|
||||
void do_reload_quest(void) {
|
||||
void do_reload_quest(void)
|
||||
{
|
||||
memset(&quest_dummy, 0, sizeof(quest_dummy));
|
||||
|
||||
quest_clear_db();
|
||||
|
123
src/map/script.c
123
src/map/script.c
@ -7538,18 +7538,18 @@ BUILDIN_FUNC(getpartyname)
|
||||
BUILDIN_FUNC(getpartymember)
|
||||
{
|
||||
struct party_data *p;
|
||||
int type = 0;
|
||||
unsigned char j = 0;
|
||||
|
||||
p = party_search(script_getnum(st,2));
|
||||
|
||||
if (p != NULL){
|
||||
if (p != NULL) {
|
||||
int type = 0;
|
||||
unsigned char i;
|
||||
|
||||
if (script_hasdata(st,3))
|
||||
type = script_getnum(st,3);
|
||||
|
||||
for (i = 0;i<MAX_PARTY;i++) {
|
||||
for (i = 0; i < MAX_PARTY; i++) {
|
||||
if (p->party.member[i].account_id) {
|
||||
switch (type) {
|
||||
case 2:
|
||||
@ -7562,10 +7562,12 @@ BUILDIN_FUNC(getpartymember)
|
||||
mapreg_setregstr(reference_uid(add_str("$@partymembername$"), j),p->party.member[i].name);
|
||||
break;
|
||||
}
|
||||
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mapreg_setreg(add_str("$@partymembercount"),j);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
@ -14328,7 +14330,6 @@ BUILDIN_FUNC(unequip) {
|
||||
|
||||
BUILDIN_FUNC(equip) {
|
||||
unsigned short nameid = 0;
|
||||
int i;
|
||||
TBL_PC *sd;
|
||||
struct item_data *item_data;
|
||||
|
||||
@ -14337,6 +14338,8 @@ BUILDIN_FUNC(equip) {
|
||||
|
||||
nameid = script_getnum(st,2);
|
||||
if ((item_data = itemdb_exists(nameid))) {
|
||||
int i;
|
||||
|
||||
ARR_FIND( 0, MAX_INVENTORY, i, sd->status.inventory[i].nameid == nameid );
|
||||
if (i < MAX_INVENTORY) {
|
||||
pc_equipitem(sd,i,item_data->equip);
|
||||
@ -14584,7 +14587,6 @@ BUILDIN_FUNC(substr)
|
||||
char *output;
|
||||
int start = script_getnum(st,3);
|
||||
int end = script_getnum(st,4);
|
||||
|
||||
int len = 0;
|
||||
|
||||
if(start >= 0 && end < strlen(str) && start <= end) {
|
||||
@ -14613,17 +14615,13 @@ BUILDIN_FUNC(explode)
|
||||
size_t len = strlen(str);
|
||||
int i = 0, j = 0;
|
||||
int start;
|
||||
|
||||
|
||||
char *temp;
|
||||
const char* name;
|
||||
|
||||
TBL_PC* sd = NULL;
|
||||
|
||||
temp = (char*)aMalloc(len + 1);
|
||||
|
||||
if( !data_isreference(data) )
|
||||
{
|
||||
if( !data_isreference(data) ) {
|
||||
ShowError("script:explode: not a variable\n");
|
||||
script_reportdata(data);
|
||||
st->state = END;
|
||||
@ -14634,24 +14632,21 @@ BUILDIN_FUNC(explode)
|
||||
start = reference_getindex(data);
|
||||
name = reference_getname(data);
|
||||
|
||||
if( not_array_variable(*name) )
|
||||
{
|
||||
if( not_array_variable(*name) ) {
|
||||
ShowError("script:explode: illegal scope\n");
|
||||
script_reportdata(data);
|
||||
st->state = END;
|
||||
return 1;// not supported
|
||||
}
|
||||
|
||||
if( !is_string_variable(name) )
|
||||
{
|
||||
if( !is_string_variable(name) ) {
|
||||
ShowError("script:explode: not string array\n");
|
||||
script_reportdata(data);
|
||||
st->state = END;
|
||||
return 1;// data type mismatch
|
||||
}
|
||||
|
||||
if( not_server_variable(*name) )
|
||||
{
|
||||
if( not_server_variable(*name) ) {
|
||||
sd = script_rid2sd(st);
|
||||
if( sd == NULL )
|
||||
return 0;// no player attached
|
||||
@ -14667,6 +14662,7 @@ BUILDIN_FUNC(explode)
|
||||
temp[j++] = str[i++];
|
||||
}
|
||||
}
|
||||
|
||||
//set last string
|
||||
temp[j] = '\0';
|
||||
set_reg(st, sd, reference_uid(id, start), name, (void*)temp, reference_getref(data));
|
||||
@ -14684,13 +14680,9 @@ BUILDIN_FUNC(implode)
|
||||
struct script_data* data = script_getdata(st, 2);
|
||||
const char *name;
|
||||
int32 glue_len = 0, array_size, id;
|
||||
|
||||
TBL_PC* sd = NULL;
|
||||
|
||||
char *output;
|
||||
|
||||
if( !data_isreference(data) )
|
||||
{
|
||||
if( !data_isreference(data) ) {
|
||||
ShowError("script:implode: not a variable\n");
|
||||
script_reportdata(data);
|
||||
st->state = END;
|
||||
@ -14700,25 +14692,23 @@ BUILDIN_FUNC(implode)
|
||||
id = reference_getid(data);
|
||||
name = reference_getname(data);
|
||||
|
||||
if( not_array_variable(*name) )
|
||||
{
|
||||
if( not_array_variable(*name) ) {
|
||||
ShowError("script:implode: illegal scope\n");
|
||||
script_reportdata(data);
|
||||
st->state = END;
|
||||
return 1;// not supported
|
||||
}
|
||||
|
||||
if( !is_string_variable(name) )
|
||||
{
|
||||
if( !is_string_variable(name) ) {
|
||||
ShowError("script:implode: not string array\n");
|
||||
script_reportdata(data);
|
||||
st->state = END;
|
||||
return 1;// data type mismatch
|
||||
}
|
||||
|
||||
if( not_server_variable(*name) )
|
||||
{
|
||||
sd = script_rid2sd(st);
|
||||
if( not_server_variable(*name) ) {
|
||||
TBL_PC* sd = script_rid2sd(st);
|
||||
|
||||
if( sd == NULL )
|
||||
return 0;// no player attached
|
||||
}
|
||||
@ -14726,8 +14716,7 @@ BUILDIN_FUNC(implode)
|
||||
//count chars
|
||||
array_size = getarraysize(st, id, reference_getindex(data), is_string_variable(name), reference_getref(data)) - 1;
|
||||
|
||||
if(array_size == -1) //empty array check (AmsTaff)
|
||||
{
|
||||
if(array_size == -1) { //empty array check (AmsTaff)
|
||||
ShowWarning("script:implode: array length = 0\n");
|
||||
output = (char*)aMalloc(sizeof(char)*5);
|
||||
sprintf(output,"%s","NULL");
|
||||
@ -14756,18 +14745,20 @@ BUILDIN_FUNC(implode)
|
||||
len = strlen(temp);
|
||||
memcpy(&output[k], temp, len);
|
||||
k += len;
|
||||
|
||||
if(glue_len != 0) {
|
||||
memcpy(&output[k], glue, glue_len);
|
||||
k += glue_len;
|
||||
}
|
||||
|
||||
script_removetop(st, -1, 0);
|
||||
}
|
||||
|
||||
temp = (char*) get_val2(st, reference_uid(id, array_size), reference_getref(data));
|
||||
len = strlen(temp);
|
||||
memcpy(&output[k], temp, len);
|
||||
k += len;
|
||||
script_removetop(st, -1, 0);
|
||||
|
||||
output[k] = '\0';
|
||||
}
|
||||
|
||||
@ -14797,7 +14788,7 @@ BUILDIN_FUNC(sprintf)
|
||||
len = strlen(format);
|
||||
|
||||
// Skip parsing, where no parsing is required.
|
||||
if(len==0){
|
||||
if(len == 0) {
|
||||
script_pushconststr(st,"");
|
||||
return 0;
|
||||
}
|
||||
@ -14806,7 +14797,7 @@ BUILDIN_FUNC(sprintf)
|
||||
CREATE(buf, char, len+1);
|
||||
|
||||
// Need not be parsed, just solve stuff like %%.
|
||||
if(argc==0){
|
||||
if(argc == 0) {
|
||||
memcpy(buf,format,len+1);
|
||||
script_pushstrcopy(st, buf);
|
||||
aFree(buf);
|
||||
@ -14818,30 +14809,36 @@ BUILDIN_FUNC(sprintf)
|
||||
// Issue sprintf for each parameter
|
||||
StringBuf_Init(&final_buf);
|
||||
q = buf;
|
||||
while((p = strchr(q, '%'))!=NULL){
|
||||
if(p!=q){
|
||||
len = p-q+1;
|
||||
if(buf2_len<len){
|
||||
while((p = strchr(q, '%')) != NULL) {
|
||||
if(p != q) {
|
||||
len = p - q + 1;
|
||||
|
||||
if(buf2_len < len) {
|
||||
RECREATE(buf2, char, len);
|
||||
buf2_len = len;
|
||||
}
|
||||
|
||||
safestrncpy(buf2, q, len);
|
||||
StringBuf_AppendStr(&final_buf, buf2);
|
||||
q = p;
|
||||
}
|
||||
p = q+1;
|
||||
if(*p=='%'){ // %%
|
||||
|
||||
p = q + 1;
|
||||
|
||||
if(*p == '%') { // %%
|
||||
StringBuf_AppendStr(&final_buf, "%");
|
||||
q+=2;
|
||||
continue;
|
||||
}
|
||||
if(*p=='n'){ // %n
|
||||
|
||||
if(*p == 'n') { // %n
|
||||
ShowWarning("buildin_sprintf: Format %%n not supported! Skipping...\n");
|
||||
script_reportsrc(st);
|
||||
q+=2;
|
||||
continue;
|
||||
}
|
||||
if(arg>=argc){
|
||||
|
||||
if(arg >= argc) {
|
||||
ShowError("buildin_sprintf: Not enough arguments passed!\n");
|
||||
if(buf) aFree(buf);
|
||||
if(buf2) aFree(buf2);
|
||||
@ -14849,14 +14846,17 @@ BUILDIN_FUNC(sprintf)
|
||||
script_pushconststr(st,"");
|
||||
return 1;
|
||||
}
|
||||
if((p = strchr(q+1, '%'))==NULL){
|
||||
|
||||
if((p = strchr(q+1, '%')) == NULL)
|
||||
p = strchr(q, 0); // EOS
|
||||
}
|
||||
len = p-q+1;
|
||||
if(buf2_len<len){
|
||||
|
||||
len = p - q + 1;
|
||||
|
||||
if(buf2_len < len) {
|
||||
RECREATE(buf2, char, len);
|
||||
buf2_len = len;
|
||||
}
|
||||
|
||||
safestrncpy(buf2, q, len);
|
||||
q = p;
|
||||
|
||||
@ -14866,18 +14866,19 @@ BUILDIN_FUNC(sprintf)
|
||||
// but it would behave in normal code the same way so it's
|
||||
// the scripter's responsibility.
|
||||
data = script_getdata(st, arg+3);
|
||||
if(data_isstring(data)){ // String
|
||||
|
||||
if(data_isstring(data)) // String
|
||||
StringBuf_Printf(&final_buf, buf2, script_getstr(st, arg+3));
|
||||
}else if(data_isint(data)){ // Number
|
||||
else if(data_isint(data)) // Number
|
||||
StringBuf_Printf(&final_buf, buf2, script_getnum(st, arg+3));
|
||||
}else if(data_isreference(data)){ // Variable
|
||||
else if(data_isreference(data)) { // Variable
|
||||
char* name = reference_getname(data);
|
||||
if(name[strlen(name)-1]=='$'){ // var Str
|
||||
|
||||
if(name[strlen(name)-1]=='$') // var Str
|
||||
StringBuf_Printf(&final_buf, buf2, script_getstr(st, arg+3));
|
||||
}else{ // var Int
|
||||
else // var Int
|
||||
StringBuf_Printf(&final_buf, buf2, script_getnum(st, arg+3));
|
||||
}
|
||||
}else{ // Unsupported type
|
||||
} else { // Unsupported type
|
||||
ShowError("buildin_sprintf: Unknown argument type!\n");
|
||||
if(buf) aFree(buf);
|
||||
if(buf2) aFree(buf2);
|
||||
@ -14885,16 +14886,16 @@ BUILDIN_FUNC(sprintf)
|
||||
script_pushconststr(st,"");
|
||||
return 1;
|
||||
}
|
||||
|
||||
arg++;
|
||||
}
|
||||
|
||||
// Append anything left
|
||||
if(*q){
|
||||
if(*q)
|
||||
StringBuf_AppendStr(&final_buf, q);
|
||||
}
|
||||
|
||||
// Passed more, than needed
|
||||
if(arg<argc){
|
||||
if(arg < argc) {
|
||||
ShowWarning("buildin_sprintf: Unused arguments passed.\n");
|
||||
script_reportsrc(st);
|
||||
}
|
||||
@ -15663,13 +15664,11 @@ BUILDIN_FUNC(npcshopdelitem)
|
||||
{
|
||||
const char* npcname = script_getstr(st,2);
|
||||
struct npc_data* nd = npc_name2id(npcname);
|
||||
unsigned short nameid;
|
||||
int n, i;
|
||||
int amount;
|
||||
int size;
|
||||
|
||||
if( !nd || ( nd->subtype != NPCTYPE_SHOP && nd->subtype != NPCTYPE_CASHSHOP && nd->subtype != NPCTYPE_ITEMSHOP && nd->subtype != NPCTYPE_POINTSHOP ) )
|
||||
{ //Not found.
|
||||
if( !nd || ( nd->subtype != NPCTYPE_SHOP && nd->subtype != NPCTYPE_CASHSHOP && nd->subtype != NPCTYPE_ITEMSHOP && nd->subtype != NPCTYPE_POINTSHOP ) ) { // Not found.
|
||||
script_pushint(st,0);
|
||||
return 0;
|
||||
}
|
||||
@ -15678,13 +15677,11 @@ BUILDIN_FUNC(npcshopdelitem)
|
||||
size = nd->u.shop.count;
|
||||
|
||||
// remove specified items from the shop item list
|
||||
for( i = 3; i < 3 + amount; i++ )
|
||||
{
|
||||
nameid = script_getnum(st,i);
|
||||
for( i = 3; i < 3 + amount; i++ ) {
|
||||
unsigned short nameid = script_getnum(st,i);
|
||||
|
||||
ARR_FIND( 0, size, n, nd->u.shop.shop_item[n].nameid == nameid );
|
||||
if( n < size )
|
||||
{
|
||||
if( n < size ) {
|
||||
memmove(&nd->u.shop.shop_item[n], &nd->u.shop.shop_item[n+1], sizeof(nd->u.shop.shop_item[0])*(size-n));
|
||||
size--;
|
||||
}
|
||||
|
@ -12,7 +12,8 @@
|
||||
|
||||
|
||||
/// failure constants for clif functions
|
||||
enum e_searchstore_failure {
|
||||
enum e_searchstore_failure
|
||||
{
|
||||
SSI_FAILED_NOTHING_SEARCH_ITEM = 0, // "No matching stores were found."
|
||||
SSI_FAILED_OVER_MAXCOUNT = 1, // "There are too many results. Please enter more detailed search term."
|
||||
SSI_FAILED_SEARCH_CNT = 2, // "You cannot search anymore."
|
||||
@ -20,81 +21,75 @@ enum e_searchstore_failure {
|
||||
SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE = 4, // "No sale (purchase) information available."
|
||||
};
|
||||
|
||||
|
||||
enum e_searchstore_searchtype {
|
||||
enum e_searchstore_searchtype
|
||||
{
|
||||
SEARCHTYPE_VENDING = 0,
|
||||
SEARCHTYPE_BUYING_STORE = 1,
|
||||
};
|
||||
|
||||
|
||||
enum e_searchstore_effecttype {
|
||||
enum e_searchstore_effecttype
|
||||
{
|
||||
EFFECTTYPE_NORMAL = 0,
|
||||
EFFECTTYPE_CASH = 1,
|
||||
EFFECTTYPE_MAX
|
||||
};
|
||||
|
||||
|
||||
/// type for shop search function
|
||||
typedef bool (*searchstore_search_t)(struct map_session_data* sd, unsigned short nameid);
|
||||
typedef bool (*searchstore_searchall_t)(struct map_session_data* sd, const struct s_search_store_search* s);
|
||||
|
||||
|
||||
/// retrieves search function by type
|
||||
static searchstore_search_t searchstore_getsearchfunc(unsigned char type)
|
||||
{
|
||||
switch( type )
|
||||
{
|
||||
switch( type ) {
|
||||
case SEARCHTYPE_VENDING: return &vending_search;
|
||||
case SEARCHTYPE_BUYING_STORE: return &buyingstore_search;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/// retrieves search-all function by type
|
||||
static searchstore_searchall_t searchstore_getsearchallfunc(unsigned char type)
|
||||
{
|
||||
switch( type )
|
||||
{
|
||||
switch( type ) {
|
||||
case SEARCHTYPE_VENDING: return &vending_searchall;
|
||||
case SEARCHTYPE_BUYING_STORE: return &buyingstore_searchall;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/// checks if the player has a store by type
|
||||
static bool searchstore_hasstore(struct map_session_data* sd, unsigned char type)
|
||||
{
|
||||
switch( type )
|
||||
{
|
||||
switch( type ) {
|
||||
case SEARCHTYPE_VENDING: return sd->state.vending;
|
||||
case SEARCHTYPE_BUYING_STORE: return sd->state.buyingstore;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// returns player's store id by type
|
||||
static int searchstore_getstoreid(struct map_session_data* sd, unsigned char type)
|
||||
{
|
||||
switch( type )
|
||||
{
|
||||
switch( type ) {
|
||||
case SEARCHTYPE_VENDING: return sd->vender_id;
|
||||
case SEARCHTYPE_BUYING_STORE: return sd->buyer_id;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool searchstore_open(struct map_session_data* sd, unsigned int uses, unsigned short effect) {
|
||||
if( !battle_config.feature_search_stores || sd->searchstore.open ) {
|
||||
bool searchstore_open(struct map_session_data* sd, unsigned int uses, unsigned short effect)
|
||||
{
|
||||
if( !battle_config.feature_search_stores || sd->searchstore.open )
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !uses || effect >= EFFECTTYPE_MAX ) {// invalid input
|
||||
if( !uses || effect >= EFFECTTYPE_MAX ) // invalid input
|
||||
return false;
|
||||
}
|
||||
|
||||
sd->searchstore.open = true;
|
||||
sd->searchstore.uses = uses;
|
||||
@ -105,7 +100,6 @@ bool searchstore_open(struct map_session_data* sd, unsigned int uses, unsigned s
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned int min_price, unsigned int max_price, const unsigned short* itemlist, unsigned int item_count, const unsigned short* cardlist, unsigned int card_count)
|
||||
{
|
||||
unsigned int i;
|
||||
@ -115,13 +109,11 @@ void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned
|
||||
searchstore_searchall_t store_searchall;
|
||||
time_t querytime;
|
||||
|
||||
if( !battle_config.feature_search_stores ) {
|
||||
if( !battle_config.feature_search_stores )
|
||||
return;
|
||||
}
|
||||
|
||||
if( !sd->searchstore.open ) {
|
||||
if( !sd->searchstore.open )
|
||||
return;
|
||||
}
|
||||
|
||||
if( ( store_searchall = searchstore_getsearchallfunc(type) ) == NULL ) {
|
||||
ShowError("searchstore_query: Unknown search type %u (account_id=%d).\n", (unsigned int)type, sd->bl.id);
|
||||
@ -156,9 +148,8 @@ void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned
|
||||
}
|
||||
}
|
||||
|
||||
if( max_price < min_price ) {
|
||||
if( max_price < min_price )
|
||||
swap(min_price, max_price);
|
||||
}
|
||||
|
||||
sd->searchstore.uses--;
|
||||
sd->searchstore.type = type;
|
||||
@ -181,11 +172,10 @@ void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned
|
||||
iter = db_iterator((type == SEARCHTYPE_VENDING) ? vending_getdb() : buyingstore_getdb());
|
||||
|
||||
for( pl_sd = dbi_first(iter); dbi_exists(iter); pl_sd = dbi_next(iter) ) {
|
||||
if( sd == pl_sd ) {// skip own shop, if any
|
||||
if( sd == pl_sd ) // skip own shop, if any
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !store_searchall(pl_sd, &s) ) {// exceeded result size
|
||||
if( !store_searchall(pl_sd, &s) ) { // exceeded result size
|
||||
clif_search_store_info_failed(sd, SSI_FAILED_OVER_MAXCOUNT);
|
||||
break;
|
||||
}
|
||||
@ -214,18 +204,17 @@ void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// checks whether or not more results are available for the client
|
||||
bool searchstore_querynext(struct map_session_data* sd) {
|
||||
if( sd->searchstore.count && ( sd->searchstore.count-1 )/SEARCHSTORE_RESULTS_PER_PAGE < sd->searchstore.pages ) {
|
||||
bool searchstore_querynext(struct map_session_data* sd)
|
||||
{
|
||||
if( sd->searchstore.count && ( sd->searchstore.count-1 )/SEARCHSTORE_RESULTS_PER_PAGE < sd->searchstore.pages )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void searchstore_next(struct map_session_data* sd) {
|
||||
void searchstore_next(struct map_session_data* sd)
|
||||
{
|
||||
if( !battle_config.feature_search_stores || !sd->searchstore.open || sd->searchstore.count <= sd->searchstore.pages*SEARCHSTORE_RESULTS_PER_PAGE )
|
||||
{// nothing (more) to display
|
||||
return;
|
||||
@ -238,11 +227,11 @@ void searchstore_next(struct map_session_data* sd) {
|
||||
sd->searchstore.pages++;
|
||||
}
|
||||
|
||||
|
||||
void searchstore_clear(struct map_session_data* sd) {
|
||||
void searchstore_clear(struct map_session_data* sd)
|
||||
{
|
||||
searchstore_clearremote(sd);
|
||||
|
||||
if( sd->searchstore.items ) {// release results
|
||||
if( sd->searchstore.items ) { // release results
|
||||
aFree(sd->searchstore.items);
|
||||
sd->searchstore.items = NULL;
|
||||
}
|
||||
@ -252,7 +241,8 @@ void searchstore_clear(struct map_session_data* sd) {
|
||||
}
|
||||
|
||||
|
||||
void searchstore_close(struct map_session_data* sd) {
|
||||
void searchstore_close(struct map_session_data* sd)
|
||||
{
|
||||
if( sd->searchstore.open ) {
|
||||
searchstore_clear(sd);
|
||||
|
||||
@ -262,31 +252,30 @@ void searchstore_close(struct map_session_data* sd) {
|
||||
}
|
||||
|
||||
|
||||
void searchstore_click(struct map_session_data* sd, int account_id, int store_id, unsigned short nameid) {
|
||||
void searchstore_click(struct map_session_data* sd, int account_id, int store_id, unsigned short nameid)
|
||||
{
|
||||
unsigned int i;
|
||||
struct map_session_data* pl_sd;
|
||||
searchstore_search_t store_search;
|
||||
|
||||
if( !battle_config.feature_search_stores || !sd->searchstore.open || !sd->searchstore.count ) {
|
||||
if( !battle_config.feature_search_stores || !sd->searchstore.open || !sd->searchstore.count )
|
||||
return;
|
||||
}
|
||||
|
||||
searchstore_clearremote(sd);
|
||||
|
||||
ARR_FIND( 0, sd->searchstore.count, i, sd->searchstore.items[i].store_id == store_id && sd->searchstore.items[i].account_id == account_id && sd->searchstore.items[i].nameid == nameid );
|
||||
if( i == sd->searchstore.count ) {// no such result, crafted
|
||||
if( i == sd->searchstore.count ) { // no such result, crafted
|
||||
ShowWarning("searchstore_click: Received request with item %hu of account %d, which is not part of current result set (account_id=%d, char_id=%d).\n", nameid, account_id, sd->bl.id, sd->status.char_id);
|
||||
clif_search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE);
|
||||
return;
|
||||
}
|
||||
|
||||
if( ( pl_sd = map_id2sd(account_id) ) == NULL ) {// no longer online
|
||||
if( ( pl_sd = map_id2sd(account_id) ) == NULL ) { // no longer online
|
||||
clif_search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE);
|
||||
return;
|
||||
}
|
||||
|
||||
if( !searchstore_hasstore(pl_sd, sd->searchstore.type) || searchstore_getstoreid(pl_sd, sd->searchstore.type) != store_id )
|
||||
{// no longer vending/buying or not same shop
|
||||
if( !searchstore_hasstore(pl_sd, sd->searchstore.type) || searchstore_getstoreid(pl_sd, sd->searchstore.type) != store_id ) { // no longer vending/buying or not same shop
|
||||
clif_search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE);
|
||||
return;
|
||||
}
|
||||
@ -301,26 +290,20 @@ void searchstore_click(struct map_session_data* sd, int account_id, int store_id
|
||||
switch( sd->searchstore.effect ) {
|
||||
case EFFECTTYPE_NORMAL:
|
||||
// display coords
|
||||
|
||||
if( sd->bl.m != pl_sd->bl.m ) {// not on same map, wipe previous marker
|
||||
if( sd->bl.m != pl_sd->bl.m ) // not on same map, wipe previous marker
|
||||
clif_search_store_info_click_ack(sd, -1, -1);
|
||||
} else {
|
||||
else
|
||||
clif_search_store_info_click_ack(sd, pl_sd->bl.x, pl_sd->bl.y);
|
||||
}
|
||||
|
||||
break;
|
||||
case EFFECTTYPE_CASH:
|
||||
// open remotely
|
||||
|
||||
// to bypass range checks
|
||||
sd->searchstore.remote_id = account_id;
|
||||
|
||||
switch( sd->searchstore.type )
|
||||
{
|
||||
switch( sd->searchstore.type ) {
|
||||
case SEARCHTYPE_VENDING: vending_vendinglistreq(sd, account_id); break;
|
||||
case SEARCHTYPE_BUYING_STORE: buyingstore_open(sd, account_id); break;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
// unknown
|
||||
@ -328,27 +311,25 @@ void searchstore_click(struct map_session_data* sd, int account_id, int store_id
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// checks whether or not sd has opened account_id's shop remotely
|
||||
bool searchstore_queryremote(struct map_session_data* sd, int account_id) {
|
||||
bool searchstore_queryremote(struct map_session_data* sd, int account_id)
|
||||
{
|
||||
return (bool)( sd->searchstore.open && sd->searchstore.count && sd->searchstore.remote_id == account_id );
|
||||
}
|
||||
|
||||
|
||||
/// removes range-check bypassing for remotely opened stores
|
||||
void searchstore_clearremote(struct map_session_data* sd) {
|
||||
void searchstore_clearremote(struct map_session_data* sd)
|
||||
{
|
||||
sd->searchstore.remote_id = 0;
|
||||
}
|
||||
|
||||
|
||||
/// receives results from a store-specific callback
|
||||
bool searchstore_result(struct map_session_data* sd, int store_id, int account_id, const char* store_name, unsigned short nameid, unsigned short amount, unsigned int price, const unsigned short* card, unsigned char refine)
|
||||
{
|
||||
struct s_search_store_info_item* ssitem;
|
||||
|
||||
if( sd->searchstore.count >= (unsigned int)battle_config.searchstore_maxresults ) {// no more
|
||||
if( sd->searchstore.count >= (unsigned int)battle_config.searchstore_maxresults ) // no more
|
||||
return false;
|
||||
}
|
||||
|
||||
ssitem = &sd->searchstore.items[sd->searchstore.count++];
|
||||
ssitem->store_id = store_id;
|
||||
|
1294
src/map/skill.c
1294
src/map/skill.c
File diff suppressed because it is too large
Load Diff
1180
src/map/status.c
1180
src/map/status.c
File diff suppressed because it is too large
Load Diff
133
src/map/trade.c
133
src/map/trade.c
@ -41,8 +41,7 @@ void trade_traderequest(struct map_session_data *sd, struct map_session_data *ta
|
||||
return;
|
||||
}
|
||||
|
||||
if (target_sd->npc_id)
|
||||
{ //Trade fails if you are using an NPC.
|
||||
if (target_sd->npc_id) { // Trade fails if you are using an NPC.
|
||||
clif_tradestart(sd, 2);
|
||||
return;
|
||||
}
|
||||
@ -56,6 +55,7 @@ void trade_traderequest(struct map_session_data *sd, struct map_session_data *ta
|
||||
|
||||
if ( sd->trade_partner != 0 ) { // If a character tries to trade to another one then cancel the previous one
|
||||
struct map_session_data *previous_sd = map_id2sd(sd->trade_partner);
|
||||
|
||||
if( previous_sd ){
|
||||
previous_sd->trade_partner = 0;
|
||||
clif_tradecancelled(previous_sd);
|
||||
@ -69,8 +69,7 @@ void trade_traderequest(struct map_session_data *sd, struct map_session_data *ta
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pc_can_give_items(sd) || !pc_can_give_items(target_sd)) //check if both GMs are allowed to trade
|
||||
{
|
||||
if (!pc_can_give_items(sd) || !pc_can_give_items(target_sd)) { // check if both GMs are allowed to trade
|
||||
clif_displaymessage(sd->fd, msg_txt(sd,246));
|
||||
clif_tradestart(sd, 2); // GM is not allowed to trade
|
||||
return;
|
||||
@ -104,22 +103,22 @@ void trade_traderequest(struct map_session_data *sd, struct map_session_data *ta
|
||||
void trade_tradeack(struct map_session_data *sd, int type)
|
||||
{
|
||||
struct map_session_data *tsd;
|
||||
|
||||
nullpo_retv(sd);
|
||||
|
||||
if (sd->state.trading || !sd->trade_partner)
|
||||
return; //Already trading or no partner set.
|
||||
return; // Already trading or no partner set.
|
||||
|
||||
if ((tsd = map_id2sd(sd->trade_partner)) == NULL) {
|
||||
clif_tradestart(sd, 1); // character does not exist
|
||||
clif_tradestart(sd, 1); // Character does not exist
|
||||
sd->trade_partner=0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (tsd->state.trading || tsd->trade_partner != sd->bl.id)
|
||||
{
|
||||
if (tsd->state.trading || tsd->trade_partner != sd->bl.id) {
|
||||
clif_tradestart(sd, 2);
|
||||
sd->trade_partner=0;
|
||||
return; //Already trading or wrong partner.
|
||||
return; // Already trading or wrong partner.
|
||||
}
|
||||
|
||||
if (type == 4) { // Cancel
|
||||
@ -145,10 +144,9 @@ void trade_tradeack(struct map_session_data *sd, int type)
|
||||
return;
|
||||
}
|
||||
|
||||
//Check if you can start trade.
|
||||
// Check if you can start trade.
|
||||
if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.storage_flag ||
|
||||
tsd->npc_id || tsd->state.vending || tsd->state.buyingstore || tsd->state.storage_flag)
|
||||
{ //Fail
|
||||
tsd->npc_id || tsd->state.vending || tsd->state.buyingstore || tsd->state.storage_flag) { // Fail
|
||||
clif_tradestart(sd, 2);
|
||||
clif_tradestart(tsd, 2);
|
||||
sd->state.deal_locked = 0;
|
||||
@ -158,7 +156,7 @@ void trade_tradeack(struct map_session_data *sd, int type)
|
||||
return;
|
||||
}
|
||||
|
||||
//Initiate trade
|
||||
// Initiate trade
|
||||
sd->state.trading = 1;
|
||||
tsd->state.trading = 1;
|
||||
memset(&sd->deal, 0, sizeof(sd->deal));
|
||||
@ -183,8 +181,7 @@ int impossible_trade_check(struct map_session_data *sd)
|
||||
|
||||
nullpo_retr(1, sd);
|
||||
|
||||
if(sd->deal.zeny > sd->status.zeny)
|
||||
{
|
||||
if(sd->deal.zeny > sd->status.zeny) {
|
||||
pc_setglobalreg(sd,"ZENY_HACKER",1);
|
||||
return -1;
|
||||
}
|
||||
@ -192,9 +189,9 @@ int impossible_trade_check(struct map_session_data *sd)
|
||||
// get inventory of player
|
||||
memcpy(&inventory, &sd->status.inventory, sizeof(struct item) * MAX_INVENTORY);
|
||||
|
||||
// remove this part: arrows can be trade and equiped
|
||||
// remove this part: arrows can be trade and equipped
|
||||
// re-added! [celest]
|
||||
// remove equiped items (they can not be trade)
|
||||
// remove equipped items (they can not be trade)
|
||||
for (i = 0; i < MAX_INVENTORY; i++)
|
||||
if (inventory[i].nameid > 0 && inventory[i].equip && !(inventory[i].equip & EQP_AMMO))
|
||||
memset(&inventory[i], 0, sizeof(struct item));
|
||||
@ -203,9 +200,10 @@ int impossible_trade_check(struct map_session_data *sd)
|
||||
for(i = 0; i < 10; i++) {
|
||||
if (!sd->deal.item[i].amount)
|
||||
continue;
|
||||
|
||||
index = sd->deal.item[i].index;
|
||||
if (inventory[index].amount < sd->deal.item[i].amount)
|
||||
{ // if more than the player have -> hack
|
||||
|
||||
if (inventory[index].amount < sd->deal.item[i].amount) { // if more than the player have -> hack
|
||||
sprintf(message_to_gm, msg_txt(sd,538), sd->status.name, sd->status.account_id); // Hack on trade: character '%s' (account: %d) try to trade more items that he has.
|
||||
intif_wis_message_to_gm(wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm);
|
||||
sprintf(message_to_gm, msg_txt(sd,539), inventory[index].amount, inventory[index].nameid, sd->deal.item[i].amount); // This player has %d of a kind of item (id: %d), and try to trade %d of them.
|
||||
@ -229,6 +227,7 @@ int impossible_trade_check(struct map_session_data *sd)
|
||||
intif_wis_message_to_gm(wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm);
|
||||
return 1;
|
||||
}
|
||||
|
||||
inventory[index].amount -= sd->deal.item[i].amount; // remove item from inventory
|
||||
}
|
||||
return 0;
|
||||
@ -247,7 +246,7 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd)
|
||||
struct item_data *data;
|
||||
int trade_i, i, n;
|
||||
|
||||
// check zenys value against hackers (Zeny was already checked on time of adding, but you never know when you lost some zeny since then.
|
||||
// check zeny value against hackers (Zeny was already checked on time of adding, but you never know when you lost some zeny since then.
|
||||
if(sd->deal.zeny > sd->status.zeny || (tsd->status.zeny > MAX_ZENY - sd->deal.zeny))
|
||||
return 0;
|
||||
if(tsd->deal.zeny > tsd->status.zeny || (sd->status.zeny > MAX_ZENY - tsd->deal.zeny))
|
||||
@ -262,44 +261,54 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd)
|
||||
short amount;
|
||||
|
||||
amount = sd->deal.item[trade_i].amount;
|
||||
|
||||
if (amount) {
|
||||
n = sd->deal.item[trade_i].index;
|
||||
|
||||
if (amount > inventory[n].amount)
|
||||
return 0; //qty Exploit?
|
||||
return 0; // Quantity Exploit?
|
||||
|
||||
data = itemdb_search(inventory[n].nameid);
|
||||
i = MAX_INVENTORY;
|
||||
if (itemdb_isstackable2(data)) { //Stackable item.
|
||||
if (itemdb_isstackable2(data)) { // Stackable item.
|
||||
for(i = 0; i < MAX_INVENTORY; i++)
|
||||
if (inventory2[i].nameid == inventory[n].nameid &&
|
||||
inventory2[i].card[0] == inventory[n].card[0] && inventory2[i].card[1] == inventory[n].card[1] &&
|
||||
inventory2[i].card[2] == inventory[n].card[2] && inventory2[i].card[3] == inventory[n].card[3]) {
|
||||
if (inventory2[i].amount + amount > MAX_AMOUNT)
|
||||
return 0;
|
||||
|
||||
inventory2[i].amount += amount;
|
||||
inventory[n].amount -= amount;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == MAX_INVENTORY) {// look for an empty slot.
|
||||
if (i == MAX_INVENTORY) { // look for an empty slot.
|
||||
for(i = 0; i < MAX_INVENTORY && inventory2[i].nameid; i++);
|
||||
if (i == MAX_INVENTORY)
|
||||
return 0;
|
||||
|
||||
memcpy(&inventory2[i], &inventory[n], sizeof(struct item));
|
||||
inventory2[i].amount = amount;
|
||||
inventory[n].amount -= amount;
|
||||
}
|
||||
}
|
||||
|
||||
amount = tsd->deal.item[trade_i].amount;
|
||||
|
||||
if (!amount)
|
||||
continue;
|
||||
|
||||
n = tsd->deal.item[trade_i].index;
|
||||
|
||||
if (amount > inventory2[n].amount)
|
||||
return 0;
|
||||
|
||||
// search if it's possible to add item (for full inventory)
|
||||
data = itemdb_search(inventory2[n].nameid);
|
||||
i = MAX_INVENTORY;
|
||||
|
||||
if (itemdb_isstackable2(data)) {
|
||||
for(i = 0; i < MAX_INVENTORY; i++)
|
||||
if (inventory[i].nameid == inventory2[n].nameid &&
|
||||
@ -307,15 +316,18 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd)
|
||||
inventory[i].card[2] == inventory2[n].card[2] && inventory[i].card[3] == inventory2[n].card[3]) {
|
||||
if (inventory[i].amount + amount > MAX_AMOUNT)
|
||||
return 0;
|
||||
|
||||
inventory[i].amount += amount;
|
||||
inventory2[n].amount -= amount;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == MAX_INVENTORY) {
|
||||
for(i = 0; i < MAX_INVENTORY && inventory[i].nameid; i++);
|
||||
if (i == MAX_INVENTORY)
|
||||
return 0;
|
||||
|
||||
memcpy(&inventory[i], &inventory2[n], sizeof(struct item));
|
||||
inventory[i].amount = amount;
|
||||
inventory2[n].amount -= amount;
|
||||
@ -339,24 +351,23 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount)
|
||||
int src_lv, dst_lv;
|
||||
|
||||
nullpo_retv(sd);
|
||||
if( !sd->state.trading || sd->state.deal_locked > 0 )
|
||||
return; //Can't add stuff.
|
||||
|
||||
if( (target_sd = map_id2sd(sd->trade_partner)) == NULL )
|
||||
{
|
||||
if( !sd->state.trading || sd->state.deal_locked > 0 )
|
||||
return; // Can't add stuff.
|
||||
|
||||
if( (target_sd = map_id2sd(sd->trade_partner)) == NULL ) {
|
||||
trade_tradecancel(sd);
|
||||
return;
|
||||
}
|
||||
|
||||
if( amount == 0 )
|
||||
{ //Why do this.. ~.~ just send an ack, the item won't display on the trade window.
|
||||
if( !amount ) { // Why do this.. ~.~ just send an ack, the item won't display on the trade window.
|
||||
clif_tradeitemok(sd, index, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
index -= 2; // 0 is for zeny, 1 is unknown. Gravity, go figure...
|
||||
|
||||
//Item checks...
|
||||
// Item checks...
|
||||
if( index < 0 || index >= MAX_INVENTORY )
|
||||
return;
|
||||
if( amount < 0 || amount > sd->status.inventory[index].amount )
|
||||
@ -365,16 +376,15 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount)
|
||||
item = &sd->status.inventory[index];
|
||||
src_lv = pc_get_group_level(sd);
|
||||
dst_lv = pc_get_group_level(target_sd);
|
||||
if( !itemdb_cantrade(item, src_lv, dst_lv) && //Can't trade
|
||||
(pc_get_partner(sd) != target_sd || !itemdb_canpartnertrade(item, src_lv, dst_lv)) ) //Can't partner-trade
|
||||
{
|
||||
|
||||
if( !itemdb_cantrade(item, src_lv, dst_lv) && // Can't trade
|
||||
(pc_get_partner(sd) != target_sd || !itemdb_canpartnertrade(item, src_lv, dst_lv)) ) { // Can't partner-trade
|
||||
clif_displaymessage (sd->fd, msg_txt(sd,260));
|
||||
clif_tradeitemok(sd, index+2, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if( item->expire_time )
|
||||
{ // Rental System
|
||||
if( item->expire_time ) { // Rental System
|
||||
clif_displaymessage (sd->fd, msg_txt(sd,260));
|
||||
clif_tradeitemok(sd, index+2, 1);
|
||||
return;
|
||||
@ -386,35 +396,31 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount)
|
||||
return;
|
||||
}
|
||||
|
||||
//Locate a trade position
|
||||
// Locate a trade position
|
||||
ARR_FIND( 0, 10, trade_i, sd->deal.item[trade_i].index == index || sd->deal.item[trade_i].amount == 0 );
|
||||
if( trade_i == 10 ) //No space left
|
||||
{
|
||||
if( trade_i == 10 ) { // No space left
|
||||
clif_tradeitemok(sd, index+2, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
trade_weight = sd->inventory_data[index]->weight * amount;
|
||||
if( target_sd->weight + sd->deal.weight + trade_weight > target_sd->max_weight )
|
||||
{ //fail to add item -- the player was over weighted.
|
||||
if( target_sd->weight + sd->deal.weight + trade_weight > target_sd->max_weight ) { // fail to add item -- the player was over weighted.
|
||||
clif_tradeitemok(sd, index+2, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if( sd->deal.item[trade_i].index == index )
|
||||
{ //The same item as before is being readjusted.
|
||||
if( sd->deal.item[trade_i].amount + amount > sd->status.inventory[index].amount )
|
||||
{ //packet deal exploit check
|
||||
if( sd->deal.item[trade_i].index == index ) { // The same item as before is being readjusted.
|
||||
if( sd->deal.item[trade_i].amount + amount > sd->status.inventory[index].amount ) { // packet deal exploit check
|
||||
amount = sd->status.inventory[index].amount - sd->deal.item[trade_i].amount;
|
||||
trade_weight = sd->inventory_data[index]->weight * amount;
|
||||
}
|
||||
|
||||
sd->deal.item[trade_i].amount += amount;
|
||||
}
|
||||
else
|
||||
{ //New deal item
|
||||
} else { // New deal item
|
||||
sd->deal.item[trade_i].index = index;
|
||||
sd->deal.item[trade_i].amount = amount;
|
||||
}
|
||||
|
||||
sd->deal.weight += trade_weight;
|
||||
|
||||
clif_tradeitemok(sd, index+2, 0); // Return the index as it was received
|
||||
@ -431,19 +437,18 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount)
|
||||
void trade_tradeaddzeny(struct map_session_data* sd, int amount)
|
||||
{
|
||||
struct map_session_data* target_sd;
|
||||
|
||||
nullpo_retv(sd);
|
||||
|
||||
if( !sd->state.trading || sd->state.deal_locked > 0 )
|
||||
return; //Can't add stuff.
|
||||
|
||||
if( (target_sd = map_id2sd(sd->trade_partner)) == NULL )
|
||||
{
|
||||
if( (target_sd = map_id2sd(sd->trade_partner)) == NULL ) {
|
||||
trade_tradecancel(sd);
|
||||
return;
|
||||
}
|
||||
|
||||
if( amount < 0 || amount > sd->status.zeny || amount > MAX_ZENY - target_sd->status.zeny )
|
||||
{ // invalid values, no appropriate packet for it => abort
|
||||
if( amount < 0 || amount > sd->status.zeny || amount > MAX_ZENY - target_sd->status.zeny ) { // invalid values, no appropriate packet for it => abort
|
||||
trade_tradecancel(sd);
|
||||
return;
|
||||
}
|
||||
@ -467,6 +472,7 @@ void trade_tradeok(struct map_session_data *sd)
|
||||
trade_tradecancel(sd);
|
||||
return;
|
||||
}
|
||||
|
||||
sd->state.deal_locked = 1;
|
||||
clif_tradeitemok(sd, 0, 0);
|
||||
clif_tradedeal_lock(sd, 0);
|
||||
@ -484,8 +490,7 @@ void trade_tradecancel(struct map_session_data *sd)
|
||||
|
||||
target_sd = map_id2sd(sd->trade_partner);
|
||||
|
||||
if(!sd->state.trading)
|
||||
{ // Not trade acepted
|
||||
if(!sd->state.trading) { // Not trade accepted
|
||||
if( target_sd ) {
|
||||
target_sd->trade_partner = 0;
|
||||
clif_tradecancelled(target_sd);
|
||||
@ -498,10 +503,12 @@ void trade_tradecancel(struct map_session_data *sd)
|
||||
for(trade_i = 0; trade_i < 10; trade_i++) { // give items back (only virtual)
|
||||
if (!sd->deal.item[trade_i].amount)
|
||||
continue;
|
||||
|
||||
clif_additem(sd, sd->deal.item[trade_i].index, sd->deal.item[trade_i].amount, 0);
|
||||
sd->deal.item[trade_i].index = 0;
|
||||
sd->deal.item[trade_i].amount = 0;
|
||||
}
|
||||
|
||||
if (sd->deal.zeny) {
|
||||
clif_updatestatus(sd, SP_ZENY);
|
||||
sd->deal.zeny = 0;
|
||||
@ -527,6 +534,7 @@ void trade_tradecancel(struct map_session_data *sd)
|
||||
clif_updatestatus(target_sd, SP_ZENY);
|
||||
target_sd->deal.zeny = 0;
|
||||
}
|
||||
|
||||
target_sd->state.deal_locked = 0;
|
||||
target_sd->trade_partner = 0;
|
||||
target_sd->state.trading = 0;
|
||||
@ -556,17 +564,19 @@ void trade_tradecommit(struct map_session_data *sd)
|
||||
if (tsd->state.deal_locked < 2)
|
||||
return; //Not yet time for trading.
|
||||
|
||||
//Now is a good time (to save on resources) to check that the trade can indeed be made and it's not exploitable.
|
||||
// Now is a good time (to save on resources) to check that the trade can indeed be made and it's not exploitable.
|
||||
// check exploit (trade more items that you have)
|
||||
if (impossible_trade_check(sd)) {
|
||||
trade_tradecancel(sd);
|
||||
return;
|
||||
}
|
||||
|
||||
// check exploit (trade more items that you have)
|
||||
if (impossible_trade_check(tsd)) {
|
||||
trade_tradecancel(tsd);
|
||||
return;
|
||||
}
|
||||
|
||||
// check for full inventory (can not add traded items)
|
||||
if (!trade_check(sd,tsd)) { // check the both players
|
||||
trade_tradecancel(sd);
|
||||
@ -574,12 +584,11 @@ void trade_tradecommit(struct map_session_data *sd)
|
||||
}
|
||||
|
||||
// trade is accepted and correct.
|
||||
for( trade_i = 0; trade_i < 10; trade_i++ )
|
||||
{
|
||||
for( trade_i = 0; trade_i < 10; trade_i++ ) {
|
||||
int n;
|
||||
unsigned char flag = 0;
|
||||
if (sd->deal.item[trade_i].amount)
|
||||
{
|
||||
|
||||
if (sd->deal.item[trade_i].amount) {
|
||||
n = sd->deal.item[trade_i].index;
|
||||
|
||||
flag = pc_additem(tsd, &sd->status.inventory[n], sd->deal.item[trade_i].amount,LOG_TYPE_TRADE);
|
||||
@ -590,8 +599,8 @@ void trade_tradecommit(struct map_session_data *sd)
|
||||
sd->deal.item[trade_i].index = 0;
|
||||
sd->deal.item[trade_i].amount = 0;
|
||||
}
|
||||
if (tsd->deal.item[trade_i].amount)
|
||||
{
|
||||
|
||||
if (tsd->deal.item[trade_i].amount) {
|
||||
n = tsd->deal.item[trade_i].index;
|
||||
|
||||
flag = pc_additem(sd, &tsd->status.inventory[n], tsd->deal.item[trade_i].amount,LOG_TYPE_TRADE);
|
||||
@ -610,6 +619,7 @@ void trade_tradecommit(struct map_session_data *sd)
|
||||
sd->deal.zeny = 0;
|
||||
|
||||
}
|
||||
|
||||
if ( tsd->deal.zeny) {
|
||||
pc_payzeny(tsd,tsd->deal.zeny,LOG_TYPE_TRADE, sd);
|
||||
pc_getzeny(sd ,tsd->deal.zeny,LOG_TYPE_TRADE, tsd);
|
||||
@ -628,8 +638,7 @@ void trade_tradecommit(struct map_session_data *sd)
|
||||
clif_tradecompleted(tsd, 0);
|
||||
|
||||
// save both player to avoid crash: they always have no advantage/disadvantage between the 2 players
|
||||
if (save_settings&1)
|
||||
{
|
||||
if (save_settings&1) {
|
||||
chrif_save(sd,0);
|
||||
chrif_save(tsd,0);
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ const short diry[8]={1,1,0,-1,-1,-1,0,1}; ///lookup to know where will move to y
|
||||
static int unit_attack_timer(int tid, unsigned int tick, int id, intptr_t data);
|
||||
static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data);
|
||||
int unit_unattackable(struct block_list *bl);
|
||||
|
||||
/**
|
||||
* Get the unit_data related to the bl
|
||||
* @param bl : Object to get the unit_data from
|
||||
@ -131,7 +132,6 @@ int unit_walktoxy_sub(struct block_list *bl)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the direct master of a bl if one exists.
|
||||
* @param bl: char to get his master [HOM|ELEM|PET|MER]
|
||||
@ -189,8 +189,7 @@ int unit_teleport_timer(int tid, unsigned int tick, int id, intptr_t data)
|
||||
if(msd && !check_distance_bl(&msd->bl, bl, data)) {
|
||||
*mast_tid = INVALID_TIMER;
|
||||
unit_warp(bl, msd->bl.m, msd->bl.x, msd->bl.y, CLR_TELEPORT );
|
||||
}
|
||||
else // No timer needed
|
||||
} else // No timer needed
|
||||
*mast_tid = INVALID_TIMER;
|
||||
}
|
||||
return 0;
|
||||
@ -227,6 +226,7 @@ int unit_check_start_teleport_timer(struct block_list *sbl)
|
||||
// If there is a master and it's a valid type
|
||||
if(msd && max_dist) {
|
||||
int *msd_tid = unit_get_masterteleport_timer(sbl);
|
||||
|
||||
if(msd_tid == NULL) return 0;
|
||||
if (!check_distance_bl(&msd->bl, sbl, max_dist)) {
|
||||
if(*msd_tid == INVALID_TIMER || *msd_tid == 0)
|
||||
@ -310,7 +310,7 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
|
||||
map_foreachinmovearea(clif_insight, bl, AREA_SIZE, -dx, -dy, sd?BL_ALL:BL_PC, bl);
|
||||
ud->walktimer = INVALID_TIMER;
|
||||
|
||||
switch(bl->type){
|
||||
switch(bl->type) {
|
||||
case BL_PC: {
|
||||
if( sd->touching_id )
|
||||
npc_touchnext_areanpc(sd,false);
|
||||
@ -704,7 +704,7 @@ int unit_run(struct block_list *bl)
|
||||
}
|
||||
|
||||
/**
|
||||
* Char movement with wugdash
|
||||
* Character movement with Warg Dash
|
||||
* @author [Jobbie/3CeAM]
|
||||
* @param bl: Object that is dashing
|
||||
* @param sd: Player
|
||||
@ -1276,6 +1276,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
|
||||
int combo = 0, range;
|
||||
|
||||
nullpo_ret(src);
|
||||
|
||||
if(status_isdead(src))
|
||||
return 0; // Do not continue source is dead
|
||||
|
||||
@ -1336,7 +1337,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
|
||||
}
|
||||
if (target)
|
||||
target_id = target->id;
|
||||
} else if (src->type==BL_HOM)
|
||||
} else if (src->type == BL_HOM)
|
||||
switch(skill_id) { // Homun-auto-target skills.
|
||||
case HLIF_HEAL:
|
||||
case HLIF_AVOID:
|
||||
@ -1481,14 +1482,14 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
|
||||
|
||||
ud->state.skillcastcancel = castcancel;
|
||||
|
||||
// temp: Used to signal force cast now.
|
||||
// Combo: Used to signal force cast now.
|
||||
combo = 0;
|
||||
|
||||
switch(skill_id) {
|
||||
case ALL_RESURRECTION:
|
||||
if(battle_check_undead(tstatus->race,tstatus->def_ele)) {
|
||||
if(battle_check_undead(tstatus->race,tstatus->def_ele))
|
||||
combo = 1;
|
||||
} else if (!status_isdead(target))
|
||||
else if (!status_isdead(target))
|
||||
return 0; // Can't cast on non-dead characters.
|
||||
break;
|
||||
case MO_FINGEROFFENSIVE:
|
||||
@ -1703,7 +1704,7 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
|
||||
/**
|
||||
* Pneuma cannot be cancelled past this point, the client displays the animation even,
|
||||
* if we cancel it from nodamage_id, so it has to be here for it to not display the animation.
|
||||
**/
|
||||
*/
|
||||
if( skill_id == AL_PNEUMA && map_getcell(src->m, skill_x, skill_y, CELL_CHKLANDPROTECTOR) ) {
|
||||
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
|
||||
return 0;
|
||||
@ -2197,7 +2198,7 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t
|
||||
/**
|
||||
* Applied when you're unable to attack (e.g. out of ammo)
|
||||
* We should stop here otherwise timer keeps on and this happens endlessly
|
||||
**/
|
||||
*/
|
||||
if( ud->attacktarget_lv == ATK_NONE )
|
||||
return 1;
|
||||
|
||||
|
@ -58,7 +58,8 @@ static void do_final_vending_autotrade(void);
|
||||
* Lookup to get the vending_db outside module
|
||||
* @return the vending_db
|
||||
*/
|
||||
DBMap * vending_getdb(){
|
||||
DBMap * vending_getdb()
|
||||
{
|
||||
return vending_db;
|
||||
}
|
||||
|
||||
@ -66,7 +67,8 @@ DBMap * vending_getdb(){
|
||||
* Create an unique vending shop id.
|
||||
* @return the next vending_id
|
||||
*/
|
||||
static int vending_getuid(void){
|
||||
static int vending_getuid(void)
|
||||
{
|
||||
return ++vending_nextid;
|
||||
}
|
||||
|
||||
@ -80,7 +82,7 @@ void vending_closevending(struct map_session_data* sd)
|
||||
|
||||
if( sd->state.vending ) {
|
||||
if( Sql_Query( mmysql_handle, "DELETE FROM `%s` WHERE vending_id = %d;", vending_items_db, sd->vender_id ) != SQL_SUCCESS ||
|
||||
Sql_Query( mmysql_handle, "DELETE FROM `%s` WHERE `id` = %d;", vendings_db, sd->vender_id ) != SQL_SUCCESS ){
|
||||
Sql_Query( mmysql_handle, "DELETE FROM `%s` WHERE `id` = %d;", vendings_db, sd->vender_id ) != SQL_SUCCESS ) {
|
||||
Sql_ShowDebug(mmysql_handle);
|
||||
}
|
||||
|
||||
@ -106,8 +108,7 @@ void vending_vendinglistreq(struct map_session_data* sd, int id)
|
||||
if( !vsd->state.vending )
|
||||
return; // not vending
|
||||
|
||||
if (!pc_can_give_items(sd) || !pc_can_give_items(vsd)) //check if both GMs are allowed to trade
|
||||
{ // GM is not allowed to trade
|
||||
if (!pc_can_give_items(sd) || !pc_can_give_items(vsd)) { //check if both GMs are allowed to trade
|
||||
clif_displaymessage(sd->fd, msg_txt(sd,246));
|
||||
return;
|
||||
}
|
||||
@ -177,13 +178,11 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui
|
||||
vend_list[i] = j;
|
||||
|
||||
z += ((double)vsd->vending[j].value * (double)amount);
|
||||
if( z > (double)sd->status.zeny || z < 0. || z > (double)MAX_ZENY )
|
||||
{
|
||||
if( z > (double)sd->status.zeny || z < 0. || z > (double)MAX_ZENY ) {
|
||||
clif_buyvending(sd, idx, amount, 1); // you don't have enough zeny
|
||||
return;
|
||||
}
|
||||
if( z + (double)vsd->status.zeny > (double)MAX_ZENY && !battle_config.vending_over_max )
|
||||
{
|
||||
if( z + (double)vsd->status.zeny > (double)MAX_ZENY && !battle_config.vending_over_max ) {
|
||||
clif_buyvending(sd, idx, vsd->vending[j].amount, 4); // too much zeny = overflow
|
||||
return;
|
||||
|
||||
@ -200,8 +199,7 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui
|
||||
|
||||
// if they try to add packets (example: get twice or more 2 apples if marchand has only 3 apples).
|
||||
// here, we check cumulative amounts
|
||||
if( vending[j].amount < amount )
|
||||
{
|
||||
if( vending[j].amount < amount ) {
|
||||
// send more quantity is not a hack (an other player can have buy items just before)
|
||||
clif_buyvending(sd, idx, vsd->vending[j].amount, 4); // not enough quantity
|
||||
return;
|
||||
@ -236,12 +234,12 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui
|
||||
pc_additem(sd, &vsd->status.cart[idx], amount, LOG_TYPE_VENDING);
|
||||
vsd->vending[vend_list[i]].amount -= amount;
|
||||
|
||||
if( vsd->vending[vend_list[i]].amount ){
|
||||
if( Sql_Query( mmysql_handle, "UPDATE `%s` SET `amount` = %d WHERE `vending_id` = %d and `cartinventory_id` = %d", vending_items_db, vsd->vending[vend_list[i]].amount, vsd->vender_id, vsd->status.cart[idx].id ) != SQL_SUCCESS ){
|
||||
if( vsd->vending[vend_list[i]].amount ) {
|
||||
if( Sql_Query( mmysql_handle, "UPDATE `%s` SET `amount` = %d WHERE `vending_id` = %d and `cartinventory_id` = %d", vending_items_db, vsd->vending[vend_list[i]].amount, vsd->vender_id, vsd->status.cart[idx].id ) != SQL_SUCCESS ) {
|
||||
Sql_ShowDebug( mmysql_handle );
|
||||
}
|
||||
}else{
|
||||
if( Sql_Query( mmysql_handle, "DELETE FROM `%s` WHERE `vending_id` = %d and `cartinventory_id` = %d", vending_items_db, vsd->vender_id, vsd->status.cart[idx].id ) != SQL_SUCCESS ){
|
||||
} else {
|
||||
if( Sql_Query( mmysql_handle, "DELETE FROM `%s` WHERE `vending_id` = %d and `cartinventory_id` = %d", vending_items_db, vsd->vender_id, vsd->status.cart[idx].id ) != SQL_SUCCESS ) {
|
||||
Sql_ShowDebug( mmysql_handle );
|
||||
}
|
||||
}
|
||||
@ -270,6 +268,7 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui
|
||||
|
||||
cursor++;
|
||||
}
|
||||
|
||||
vsd->vend_num = cursor;
|
||||
|
||||
//Always save BOTH: customer (buyer) and vender
|
||||
@ -299,7 +298,8 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui
|
||||
* @param count : number of different items
|
||||
* @return 0 If success, 1 - Cannot open (die, not state.prevend, trading), 2 - No cart, 3 - Count issue, 4 - Cart data isn't saved yet, 5 - No valid item found
|
||||
*/
|
||||
char vending_openvending(struct map_session_data* sd, const char* message, const uint8* data, int count) {
|
||||
char vending_openvending(struct map_session_data* sd, const char* message, const uint8* data, int count)
|
||||
{
|
||||
int i, j;
|
||||
int vending_skill_lvl;
|
||||
char message_sql[MESSAGE_SIZE*2];
|
||||
@ -319,8 +319,7 @@ char vending_openvending(struct map_session_data* sd, const char* message, const
|
||||
}
|
||||
|
||||
// check number of items in shop
|
||||
if( count < 1 || count > MAX_VENDING || count > 2 + vending_skill_lvl )
|
||||
{ // invalid item count
|
||||
if( count < 1 || count > MAX_VENDING || count > 2 + vending_skill_lvl ) { // invalid item count
|
||||
clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0);
|
||||
return 3;
|
||||
}
|
||||
@ -372,6 +371,7 @@ char vending_openvending(struct map_session_data* sd, const char* message, const
|
||||
clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); // custom reply packet
|
||||
return 5;
|
||||
}
|
||||
|
||||
sd->state.prevend = 0;
|
||||
sd->state.vending = true;
|
||||
sd->vender_id = vending_getuid();
|
||||
@ -382,12 +382,12 @@ char vending_openvending(struct map_session_data* sd, const char* message, const
|
||||
|
||||
if( Sql_Query( mmysql_handle, "INSERT INTO `%s`(`id`,`account_id`,`char_id`,`sex`,`map`,`x`,`y`,`title`,`autotrade`, `body_direction`, `head_direction`, `sit`) "
|
||||
"VALUES( %d, %d, %d, '%c', '%s', %d, %d, '%s', %d, '%d', '%d', '%d' );",
|
||||
vendings_db, sd->vender_id, sd->status.account_id, sd->status.char_id, sd->status.sex == 0 ? 'F' : 'M', map[sd->bl.m].name, sd->bl.x, sd->bl.y, message_sql, sd->state.autotrade, sd->ud.dir, sd->head_dir, pc_issit(sd) ) != SQL_SUCCESS ){
|
||||
vendings_db, sd->vender_id, sd->status.account_id, sd->status.char_id, sd->status.sex == 0 ? 'F' : 'M', map[sd->bl.m].name, sd->bl.x, sd->bl.y, message_sql, sd->state.autotrade, sd->ud.dir, sd->head_dir, pc_issit(sd) ) != SQL_SUCCESS ) {
|
||||
Sql_ShowDebug(mmysql_handle);
|
||||
}
|
||||
|
||||
for( i = 0; i < count; i++ ) {
|
||||
if( Sql_Query( mmysql_handle, "INSERT INTO `%s`(`vending_id`,`index`,`cartinventory_id`,`amount`,`price`) VALUES( %d, %d, %d, %d, %d );", vending_items_db, sd->vender_id, i, sd->status.cart[sd->vending[i].index].id, sd->vending[i].amount, sd->vending[i].value ) != SQL_SUCCESS ){
|
||||
if( Sql_Query( mmysql_handle, "INSERT INTO `%s`(`vending_id`,`index`,`cartinventory_id`,`amount`,`price`) VALUES( %d, %d, %d, %d, %d );", vending_items_db, sd->vender_id, i, sd->status.cart[sd->vending[i].index].id, sd->vending[i].amount, sd->vending[i].value ) != SQL_SUCCESS ) {
|
||||
Sql_ShowDebug(mmysql_handle);
|
||||
}
|
||||
}
|
||||
@ -406,7 +406,8 @@ char vending_openvending(struct map_session_data* sd, const char* message, const
|
||||
* @param nameid : item id
|
||||
* @return 0:not selling it, 1: yes
|
||||
*/
|
||||
bool vending_search(struct map_session_data* sd, unsigned short nameid) {
|
||||
bool vending_search(struct map_session_data* sd, unsigned short nameid)
|
||||
{
|
||||
int i;
|
||||
|
||||
if( !sd->state.vending ) { // not vending
|
||||
@ -421,15 +422,14 @@ bool vending_search(struct map_session_data* sd, unsigned short nameid) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Searches for all items in a vending, that match given ids, price and possible cards.
|
||||
* @param sd : The vender session to search into
|
||||
* @param s : parameter of the search (see s_search_store_search)
|
||||
* @return Whether or not the search should be continued.
|
||||
*/
|
||||
bool vending_searchall(struct map_session_data* sd, const struct s_search_store_search* s) {
|
||||
bool vending_searchall(struct map_session_data* sd, const struct s_search_store_search* s)
|
||||
{
|
||||
int i, c, slot;
|
||||
unsigned int idx, cidx;
|
||||
struct item* it;
|
||||
@ -439,40 +439,38 @@ bool vending_searchall(struct map_session_data* sd, const struct s_search_store_
|
||||
|
||||
for( idx = 0; idx < s->item_count; idx++ ) {
|
||||
ARR_FIND( 0, sd->vend_num, i, sd->status.cart[sd->vending[i].index].nameid == (short)s->itemlist[idx] );
|
||||
if( i == sd->vend_num ) {// not found
|
||||
if( i == sd->vend_num ) { // not found
|
||||
continue;
|
||||
}
|
||||
it = &sd->status.cart[sd->vending[i].index];
|
||||
|
||||
if( s->min_price && s->min_price > sd->vending[i].value ) {// too low price
|
||||
if( s->min_price && s->min_price > sd->vending[i].value ) { // too low price
|
||||
continue;
|
||||
}
|
||||
|
||||
if( s->max_price && s->max_price < sd->vending[i].value ) {// too high price
|
||||
if( s->max_price && s->max_price < sd->vending[i].value ) { // too high price
|
||||
continue;
|
||||
}
|
||||
|
||||
if( s->card_count ) {// check cards
|
||||
if( itemdb_isspecial(it->card[0]) ) {// something, that is not a carded
|
||||
if( s->card_count ) { // check cards
|
||||
if( itemdb_isspecial(it->card[0]) ) { // something, that is not a carded
|
||||
continue;
|
||||
}
|
||||
slot = itemdb_slot(it->nameid);
|
||||
|
||||
for( c = 0; c < slot && it->card[c]; c ++ ) {
|
||||
ARR_FIND( 0, s->card_count, cidx, s->cardlist[cidx] == it->card[c] );
|
||||
if( cidx != s->card_count )
|
||||
{// found
|
||||
if( cidx != s->card_count ) { // found
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( c == slot || !it->card[c] ) {// no card match
|
||||
if( c == slot || !it->card[c] ) { // no card match
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if( !searchstore_result(s->search_sd, sd->vender_id, sd->status.account_id, sd->message, it->nameid, sd->vending[i].amount, sd->vending[i].value, it->card, it->refine) )
|
||||
{// result set full
|
||||
if( !searchstore_result(s->search_sd, sd->vender_id, sd->status.account_id, sd->message, it->nameid, sd->vending[i].amount, sd->vending[i].value, it->card, it->refine) ) { // result set full
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -484,11 +482,12 @@ bool vending_searchall(struct map_session_data* sd, const struct s_search_store_
|
||||
* Open vending for Autotrader
|
||||
* @param sd Player as autotrader
|
||||
*/
|
||||
void vending_reopen( struct map_session_data* sd ){
|
||||
void vending_reopen( struct map_session_data* sd )
|
||||
{
|
||||
nullpo_retv(sd);
|
||||
|
||||
// Ready to open vending for this char
|
||||
if ( autotrader_count > 0 && autotraders){
|
||||
if ( autotrader_count > 0 && autotraders) {
|
||||
uint16 i;
|
||||
uint8 *data, *p, fail = 0;
|
||||
uint16 j, count;
|
||||
@ -530,12 +529,11 @@ void vending_reopen( struct map_session_data* sd ){
|
||||
pc_cleareventtimer(sd);
|
||||
|
||||
// Open the vending again
|
||||
if( (fail = vending_openvending(sd, autotraders[i]->title, data, count)) == 0 ){
|
||||
if( (fail = vending_openvending(sd, autotraders[i]->title, data, count)) == 0 ) {
|
||||
// Set him to autotrade
|
||||
if (Sql_Query( mmysql_handle, "UPDATE `%s` SET `autotrade` = 1, `body_direction` = '%d', `head_direction` = '%d', `sit` = '%d' "
|
||||
"WHERE `id` = %d;",
|
||||
vendings_db, autotraders[i]->dir, autotraders[i]->head_dir, autotraders[i]->sit, sd->vender_id ) != SQL_SUCCESS )
|
||||
{
|
||||
vendings_db, autotraders[i]->dir, autotraders[i]->head_dir, autotraders[i]->sit, sd->vender_id ) != SQL_SUCCESS ) {
|
||||
Sql_ShowDebug( mmysql_handle );
|
||||
}
|
||||
|
||||
@ -553,7 +551,7 @@ void vending_reopen( struct map_session_data* sd ){
|
||||
|
||||
ShowInfo("Loaded vending for '"CL_WHITE"%s"CL_RESET"' with '"CL_WHITE"%d"CL_RESET"' items at "CL_WHITE"%s (%d,%d)"CL_RESET"\n",
|
||||
sd->status.name, count, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y);
|
||||
}else{
|
||||
} else {
|
||||
// Failed to open the vending, set him offline
|
||||
ShowError("Failed (%d) to load autotrade vending data for '"CL_WHITE"%s"CL_RESET"' with '"CL_WHITE"%d"CL_RESET"' items\n", fail, sd->status.name, count );
|
||||
|
||||
@ -571,7 +569,8 @@ void vending_reopen( struct map_session_data* sd ){
|
||||
/**
|
||||
* Initializing autotraders from table
|
||||
*/
|
||||
void do_init_vending_autotrade( void ) {
|
||||
void do_init_vending_autotrade(void)
|
||||
{
|
||||
if (battle_config.feature_autotrade) {
|
||||
uint16 i, items = 0;
|
||||
autotrader_count = autotrader_loaded_count = 0;
|
||||
@ -583,13 +582,12 @@ void do_init_vending_autotrade( void ) {
|
||||
"FROM `%s` "
|
||||
"WHERE `autotrade` = 1 AND (SELECT COUNT(`vending_id`) FROM `%s` WHERE `vending_id` = `id`) > 0 "
|
||||
"ORDER BY `id`;",
|
||||
vendings_db, vending_items_db ) != SQL_SUCCESS )
|
||||
{
|
||||
vendings_db, vending_items_db ) != SQL_SUCCESS ) {
|
||||
Sql_ShowDebug(mmysql_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
if( (autotrader_count = (uint16)Sql_NumRows(mmysql_handle)) > 0 ){
|
||||
if( (autotrader_count = (uint16)Sql_NumRows(mmysql_handle)) > 0 ) {
|
||||
// Init autotraders
|
||||
CREATE(autotraders, struct s_autotrade *, autotrader_count);
|
||||
|
||||
@ -637,7 +635,7 @@ void do_init_vending_autotrade( void ) {
|
||||
Sql_FreeResult(mmysql_handle);
|
||||
|
||||
//Init items on vending list each autotrader
|
||||
for (i = 0; i < autotrader_count; i++){
|
||||
for (i = 0; i < autotrader_count; i++) {
|
||||
struct s_autotrade *at = NULL;
|
||||
uint16 j;
|
||||
|
||||
@ -649,8 +647,7 @@ void do_init_vending_autotrade( void ) {
|
||||
"FROM `%s` "
|
||||
"WHERE `vending_id` = %d "
|
||||
"ORDER BY `index` ASC;",
|
||||
vending_items_db, at->vendor_id ) )
|
||||
{
|
||||
vending_items_db, at->vendor_id ) ) {
|
||||
Sql_ShowDebug(mmysql_handle);
|
||||
continue;
|
||||
}
|
||||
@ -684,8 +681,7 @@ void do_init_vending_autotrade( void ) {
|
||||
|
||||
// Everything is loaded fine, their entries will be reinserted once they are loaded
|
||||
if (Sql_Query( mmysql_handle, "DELETE FROM `%s`;", vendings_db ) != SQL_SUCCESS ||
|
||||
Sql_Query( mmysql_handle, "DELETE FROM `%s`;", vending_items_db ) != SQL_SUCCESS)
|
||||
{
|
||||
Sql_Query( mmysql_handle, "DELETE FROM `%s`;", vending_items_db ) != SQL_SUCCESS) {
|
||||
Sql_ShowDebug(mmysql_handle);
|
||||
}
|
||||
}
|
||||
@ -694,8 +690,9 @@ void do_init_vending_autotrade( void ) {
|
||||
* Clear all autotraders
|
||||
* @author [Cydh]
|
||||
*/
|
||||
void do_final_vending_autotrade(void) {
|
||||
if (autotrader_count && autotraders){
|
||||
void do_final_vending_autotrade(void)
|
||||
{
|
||||
if (autotrader_count && autotraders) {
|
||||
uint16 i = 0;
|
||||
while (i < autotrader_count) { //Free the autotrader
|
||||
if (autotraders[i] == NULL)
|
||||
@ -723,7 +720,8 @@ void do_final_vending_autotrade(void) {
|
||||
* Initialise the vending module
|
||||
* called in map::do_init
|
||||
*/
|
||||
void do_final_vending(void) {
|
||||
void do_final_vending(void)
|
||||
{
|
||||
db_destroy(vending_db);
|
||||
do_final_vending_autotrade(); //Make sure everything is cleared [Cydh]
|
||||
}
|
||||
@ -732,7 +730,8 @@ void do_final_vending(void) {
|
||||
* Destory the vending module
|
||||
* called in map::do_final
|
||||
*/
|
||||
void do_init_vending(void) {
|
||||
void do_init_vending(void)
|
||||
{
|
||||
vending_db = idb_alloc(DB_OPT_BASE);
|
||||
vending_nextid = 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user