summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/char/char.c22
-rw-r--r--src/common/socket.c11
-rw-r--r--src/config/const.h7
-rw-r--r--src/map/battle.c42
-rw-r--r--src/map/script.c45
-rw-r--r--src/map/skill.c62
-rw-r--r--src/map/status.c2
7 files changed, 130 insertions, 61 deletions
diff --git a/src/char/char.c b/src/char/char.c
index b18beed60..698832bfb 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -453,16 +453,31 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p)
(p->head_mid != cp->head_mid) || (p->head_bottom != cp->head_bottom) || (p->delete_date != cp->delete_date) ||
(p->rename != cp->rename) || (p->slotchange != cp->slotchange) || (p->robe != cp->robe) ||
(p->show_equip != cp->show_equip) || (p->allow_party != cp->allow_party) || (p->font != cp->font) ||
- (p->uniqueitem_counter != cp->uniqueitem_counter )
+ (p->uniqueitem_counter != cp->uniqueitem_counter ) || (p->sex != cp->sex)
) {
//Save status
unsigned int opt = 0;
+ char sex;
if( p->allow_party )
opt |= OPT_ALLOW_PARTY;
if( p->show_equip )
opt |= OPT_SHOW_EQUIP;
+ switch (p->sex)
+ {
+ case 0:
+ sex = 'F';
+ break;
+ case 1:
+ sex = 'M';
+ break;
+ case 99:
+ default:
+ sex = 'U';
+ break;
+ }
+
if( SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `base_level`='%d', `job_level`='%d',"
"`base_exp`='%u', `job_exp`='%u', `zeny`='%d',"
"`max_hp`='%d',`hp`='%d',`max_sp`='%d',`sp`='%d',`status_point`='%d',`skill_point`='%d',"
@@ -470,7 +485,8 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p)
"`option`='%d',`party_id`='%d',`guild_id`='%d',`pet_id`='%d',`homun_id`='%d',`elemental_id`='%d',"
"`weapon`='%d',`shield`='%d',`head_top`='%d',`head_mid`='%d',`head_bottom`='%d',"
"`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d', `rename`='%d',"
- "`delete_date`='%lu',`robe`='%d',`slotchange`='%d', `char_opt`='%u', `font`='%u', `uniqueitem_counter` ='%u'"
+ "`delete_date`='%lu',`robe`='%d',`slotchange`='%d', `char_opt`='%u', `font`='%u', `uniqueitem_counter` ='%u',"
+ " sex = '%c'"
" WHERE `account_id`='%d' AND `char_id` = '%d'",
char_db, p->base_level, p->job_level,
p->base_exp, p->job_exp, p->zeny,
@@ -481,7 +497,7 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p)
mapindex_id2name(p->last_point.map), p->last_point.x, p->last_point.y,
mapindex_id2name(p->save_point.map), p->save_point.x, p->save_point.y, p->rename,
(unsigned long)p->delete_date, // FIXME: platform-dependent size
- p->robe,p->slotchange,opt,p->font,p->uniqueitem_counter,
+ p->robe,p->slotchange,opt,p->font,p->uniqueitem_counter, sex,
p->account_id, p->char_id) )
{
Sql_ShowDebug(inter->sql_handle);
diff --git a/src/common/socket.c b/src/common/socket.c
index f307dc4a9..09521c312 100644
--- a/src/common/socket.c
+++ b/src/common/socket.c
@@ -29,8 +29,12 @@
# include <errno.h>
# include <net/if.h>
# include <netdb.h>
+#if defined __linux__ || defined __linux
+# include <linux/tcp.h>
+#else
# include <netinet/in.h>
# include <netinet/tcp.h>
+#endif
# include <sys/ioctl.h>
# include <sys/socket.h>
# include <sys/time.h>
@@ -333,6 +337,13 @@ void setsocketopts(int fd, struct hSockOpt *opt) {
lopt.l_linger = 0; // Do not care
if( sSetsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&lopt, sizeof(lopt)) )
ShowWarning("setsocketopts: Unable to set SO_LINGER mode for connection #%d!\n", fd);
+
+#ifdef TCP_THIN_LINEAR_TIMEOUTS
+ setsockopt(fd, IPPROTO_TCP, TCP_THIN_LINEAR_TIMEOUTS, &yes, sizeof yes);
+#endif
+#ifdef TCP_THIN_DUPACK
+ setsockopt(fd, IPPROTO_TCP, TCP_THIN_DUPACK, &yes, sizeof yes);
+#endif
}
/*======================================
diff --git a/src/config/const.h b/src/config/const.h
index 7b5ed5506..e10d2ad2a 100644
--- a/src/config/const.h
+++ b/src/config/const.h
@@ -73,17 +73,16 @@
/* Renewal's dmg level modifier, used as a macro for a easy way to turn off. */
#ifdef RENEWAL_LVDMG
#define RE_LVL_DMOD(val) do { \
- if( status->get_lv(src) > 100 && (val) > 0 ) \
+ if( (val) > 0 ) \
skillratio = skillratio * status->get_lv(src) / (val); \
} while(0)
#define RE_LVL_MDMOD(val) do { \
- if( status->get_lv(src) > 100 && (val) > 0) \
+ if ( (val) > 0 ) \
md.damage = md.damage * status->get_lv(src) / (val); \
} while(0)
/* ranger traps special */
#define RE_LVL_TMDMOD() do { \
- if( status->get_lv(src) > 100 ) \
- md.damage = md.damage * 150 / 100 + md.damage * status->get_lv(src) / 100; \
+ md.damage = md.damage * 150 / 100 + md.damage * status->get_lv(src) / 100; \
} while(0)
#else
#define RE_LVL_DMOD(val)
diff --git a/src/map/battle.c b/src/map/battle.c
index bbb03eb1f..77edb31f1 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -2078,11 +2078,6 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
case NJ_KIRIKAGE:
skillratio += 100 * (skill_lv-1);
break;
-#ifdef RENEWAL
- case NJ_KUNAI:
- skillratio += 50 + 150 * skill_lv;
- break;
-#endif
case KN_CHARGEATK:
{
int k = (flag-1)/3; //+100% every 3 cells of distance
@@ -2521,6 +2516,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
RE_LVL_DMOD(120);
if( tsc && tsc->data[SC_KO_JYUMONJIKIRI] )
skillratio += status->get_lv(src) * skill_lv;
+ break;
case KO_HUUMARANKA:
skillratio += -100 + 150 * skill_lv + status_get_agi(src) + status_get_dex(src) + 100 * (sd ? pc->checkskill(sd, NJ_HUUMA) : 0);
break;
@@ -2528,11 +2524,6 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
skillratio += -100 + 100 * skill_lv;
RE_LVL_DMOD(100);
break;
- case KO_BAKURETSU:
- skillratio += -100 + (50 + status_get_dex(src) / 4) * skill_lv * (sd?pc->checkskill(sd,NJ_TOBIDOUGU):10) * 4 / 100;
- RE_LVL_DMOD(120);
- skillratio += 10 * (sd ? sd->status.job_level : 0);
- break;
case MH_NEEDLE_OF_PARALYZE:
skillratio += 600 + 100 * skill_lv;
break;
@@ -3933,14 +3924,16 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
break;
case KO_HAPPOKUNAI:
{
- struct Damage wd = battle->calc_weapon_attack(src,target,skill_id,skill_lv,mflag);
+ struct Damage wd = battle->calc_weapon_attack(src, target, 0, 1, mflag);
#ifdef RENEWAL
short totaldef = status->get_total_def(target);
#else
short totaldef = tstatus->def2 + (short)status->get_def(target);
#endif
- md.damage = 3 * wd.damage * (5 + skill_lv) / 5;
+ if ( sd ) wd.damage += sd->bonus.arrow_atk;
+ md.damage = (int)(3 * (1 + wd.damage) * (5 + skill_lv) / 5.0f);
md.damage -= totaldef;
+
}
break;
}
@@ -4242,10 +4235,14 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
wd.div_ = tstatus->size + 2 + ( (rnd()%100 < 50-tstatus->size*10) ? 1 : 0 );
break;
#ifdef RENEWAL
+ case NJ_KUNAI:
case HW_MAGICCRASHER:
+ case NJ_SYURIKEN:
+ case GS_MAGICALBULLET:
+#endif
+ case KO_BAKURETSU:
flag.tdef = 1;
break;
-#endif
}
} else //Range for normal attacks.
wd.flag |= flag.arrow?BF_LONG:BF_SHORT;
@@ -4597,7 +4594,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
break;
case NJ_SYURIKEN: // [malufett]
GET_NORMAL_ATTACK( (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0) );
- wd.damage += battle->calc_masteryfix(src, target, skill_id, skill_lv, 4 * skill_lv + (sd ? sd->bonus.arrow_atk : 0), wd.div_, 0, flag.weapon) - status->get_total_def(target);
+ wd.damage += battle->calc_masteryfix(src, target, skill_id, skill_lv, 4 * skill_lv + (sd ? sd->bonus.arrow_atk : 0), wd.div_, 0, flag.weapon);
break;
case MO_EXTREMITYFIST: // [malufett]
{
@@ -4736,13 +4733,6 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
status_change_end(src, SC_EXEEDBREAK, INVALID_TIMER);
}
-
- #ifdef RENEWAL
- if( sd && skill_id == NJ_KUNAI ){
- flag.tdef = 1;
- ATK_ADD( sd->bonus.arrow_atk );
- }
- #endif
switch(skill_id){
case SR_GATEOFHELL:
if (wd.dmg_lv != ATK_FLEE)
@@ -4776,6 +4766,15 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
wd.damage = battle->calc_masteryfix(src, target, skill_id, skill_lv, wd.damage, wd.div_, 0, flag.weapon);
}
#endif
+
+ case KO_BAKURETSU:
+ {
+ GET_NORMAL_ATTACK((sc && sc->data[SC_MAXIMIZEPOWER] ? 1 : 0) | (sc && sc->data[SC_WEAPONPERFECT] ? 8 : 0));
+ skillratio = skill_lv * (50 + status_get_dex(src) / 4);
+ skillratio = (int)(skillratio * (sd ? pc->checkskill(sd, NJ_TOBIDOUGU) : 10) * 40.f / 100.0f * status->get_lv(src) / 120);
+ ATK_RATE(skillratio + 10 * (sd ? sd->status.job_level : 0));
+ }
+ break;
default:
ATK_RATE(battle->calc_skillratio(BF_WEAPON, src, target, skill_id, skill_lv, skillratio, wflag));
}
@@ -4805,7 +4804,6 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
ATK_ADD( status->get_matk(src, 2) );
#else
ATK_ADD( battle->calc_magic_attack(src, target, skill_id, skill_lv, wflag).damage );
- flag.tdef = 1;
#endif
#ifndef RENEWAL
case NJ_SYURIKEN:
diff --git a/src/map/script.c b/src/map/script.c
index c7b1ae849..031dfc21b 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -10639,27 +10639,51 @@ BUILDIN(changebase) {
return true;
}
+static TBL_PC *prepareChangeSex(struct script_state* st)
+{
+ int i;
+ TBL_PC *sd = script->rid2sd(st);
+
+ if (sd == NULL)
+ return NULL;
+
+ pc->resetskill(sd, 4);
+ // to avoid any problem with equipment and invalid sex, equipment is unequiped.
+ for (i=0; i<EQI_MAX; i++)
+ if (sd->equip_index[i] >= 0) pc->unequipitem(sd, sd->equip_index[i], 3);
+ return sd;
+}
+
/*==========================================
* Unequip all item and request for a changesex to char-serv
*------------------------------------------*/
BUILDIN(changesex)
{
- int i;
- TBL_PC *sd = NULL;
- sd = script->rid2sd(st);
-
- if( sd == NULL )
+ TBL_PC *sd = prepareChangeSex(st);
+ if (sd == NULL)
return false;
-
- pc->resetskill(sd,4);
- // to avoid any problem with equipment and invalid sex, equipment is unequiped.
- for( i=0; i<EQI_MAX; i++ )
- if( sd->equip_index[i] >= 0 ) pc->unequipitem(sd, sd->equip_index[i], 3);
chrif->changesex(sd);
return true;
}
/*==========================================
+ * Unequip all items and change character sex [4144]
+ *------------------------------------------*/
+BUILDIN(changecharsex)
+{
+ TBL_PC *sd = prepareChangeSex(st);
+ if (sd == NULL)
+ return false;
+ if (sd->status.sex == 99)
+ sd->status.sex = 0;
+ sd->status.sex = sd->status.sex ? 0 : 1;
+ chrif->save(sd, 0);
+ if (sd->fd)
+ clif->authfail_fd(sd->fd, 15);
+ return true;
+}
+
+/*==========================================
* Works like 'announce' but outputs in the common chat window
*------------------------------------------*/
BUILDIN(globalmes) {
@@ -19302,6 +19326,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(skillpointcount,""),
BUILDIN_DEF(changebase,"i?"),
BUILDIN_DEF(changesex,""),
+ BUILDIN_DEF(changecharsex,""), // [4144]
BUILDIN_DEF(waitingroom,"si?????"),
BUILDIN_DEF(delwaitingroom,"?"),
BUILDIN_DEF2(waitingroomkickall,"kickwaitingroomall","?"),
diff --git a/src/map/skill.c b/src/map/skill.c
index b80779e92..5eb319c02 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -3574,7 +3574,6 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
case WM_SEVERE_RAINSTORM_MELEE:
case WM_GREAT_ECHO:
case GN_SLINGITEM_RANGEMELEEATK:
- case KO_JYUMONJIKIRI:
case KO_SETSUDAN:
case GC_DARKCROW:
case LG_OVERBRAND_BRANDISH:
@@ -4216,27 +4215,27 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
}
break;
+ case KO_JYUMONJIKIRI:
case GC_DARKILLUSION:
{
short x, y;
- short dir = map->calc_dir(src,bl->x,bl->y);
+ short dir = map->calc_dir(bl, src->x, src->y);
- if( dir > 0 && dir < 4) x = 2;
- else if( dir > 4 ) x = -2;
- else x = 0;
- if( dir > 2 && dir < 6 ) y = 2;
- else if( dir == 7 || dir < 2 ) y = -2;
- else y = 0;
+ if ( dir < 4 ) {
+ x = bl->x + 2 * (dir > 0) - 3 * (dir > 0);
+ y = bl->y + 1 - (dir / 2) - (dir > 2);
+ } else {
+ x = bl->x + 2 * (dir > 4) - 1 * (dir > 4);
+ y = bl->y + (dir / 6) - 1 + (dir > 6);
+ }
- if( unit->movepos(src, bl->x+x, bl->y+y, 1, 1) )
- {
- clif->slide(src,bl->x+x,bl->y+y);
+ if ( unit->movepos(src, x, y, 1, 1) ) {
+ clif->slide(src, x, y);
clif->fixpos(src); // the official server send these two packets.
- skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
- if( rnd()%100 < 4 * skill_lv )
- skill->castend_damage_id(src,bl,GC_CROSSIMPACT,skill_lv,tick,flag);
+ skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag);
+ if ( rnd() % 100 < 4 * skill_lv && skill_id == GC_DARKILLUSION )
+ skill->castend_damage_id(src, bl, GC_CROSSIMPACT, skill_lv, tick, flag);
}
-
}
break;
case GC_WEAPONCRUSH:
@@ -6041,7 +6040,6 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case MO_ABSORBSPIRITS:
{
int sp = 0;
- int i;
if ( dstsd && dstsd->spiritball
&& (sd == dstsd || map_flag_vs(src->m) || (sd->duel_group && sd->duel_group == dstsd->duel_group))
&& ((dstsd->class_&MAPID_BASEMASK) != MAPID_GUNSLINGER || (dstsd->class_&MAPID_UPPERMASK) != MAPID_REBELLION)
@@ -6055,7 +6053,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
mob->target(dstmd,src,0);
}
if ( dstsd ) {
- for (i = SPIRITS_TYPE_CHARM_WATER; i < SPIRITS_TYPE_SPHERE; i++)
+ int i;
+ for ( i = SPIRITS_TYPE_CHARM_WATER; i < SPIRITS_TYPE_SPHERE; i++ )
pc->del_charm(dstsd, dstsd->spiritcharm[i], i);
}
if (sp) status->heal(src, 0, sp, 3);
@@ -11067,7 +11066,7 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
break;
case BA_ASSASSINCROSS:
if(sd)
- val1 = (pc->checkskill(sd,BA_MUSICALLESSON) + 1) / 2;
+ val1 = pc->checkskill(sd,BA_MUSICALLESSON) / 2;
#ifdef RENEWAL
// This formula was taken from a RE calculator
// and the changes published on irowiki
@@ -11908,19 +11907,38 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
int heal;
#ifdef RENEWAL
struct mob_data *md = BL_CAST(BL_MOB, bl);
- if( md && md->class_ == MOBID_EMPERIUM )
+ if (md && md->class_ == MOBID_EMPERIUM)
break;
#endif
- if( (sg->src_id == bl->id && !(tsc && tsc->data[SC_SOULLINK] && tsc->data[SC_SOULLINK]->val2 == SL_BARDDANCER))
+ if ((sg->src_id == bl->id && !(tsc && tsc->data[SC_SOULLINK] && tsc->data[SC_SOULLINK]->val2 == SL_BARDDANCER))
|| (!(battle_config.song_timer_reset) && tsc && tsc->data[type] && tsc->data[type]->val4 == 1))
break;
+
heal = skill->calc_heal(ss,bl,sg->skill_id, sg->skill_lv, true);
if( tsc->data[SC_AKAITSUKI] && heal )
heal = ~heal + 1;
clif->skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1);
status->heal(bl, heal, 0, 0);
+
+ if (!battle_config.song_timer_reset)
+ sc_start4(ss, bl, type, 100, sg->skill_lv, sg->val1, sg->val2, 0, sg->limit);
}
break;
+ case UNT_POEMBRAGI:
+ case UNT_WHISTLE:
+ case UNT_ASSASSINCROSS:
+ case UNT_HUMMING:
+ case UNT_DONTFORGETME:
+ case UNT_FORTUNEKISS:
+ case UNT_SERVICEFORYOU:
+ if (battle_config.song_timer_reset
+ || (!(battle_config.song_timer_reset) && tsc && tsc->data[type] && tsc->data[type]->val4 == 1)
+ || (sg->src_id == bl->id && !(tsc && tsc->data[SC_SOULLINK] && tsc->data[SC_SOULLINK]->val2 == SL_BARDDANCER))
+ )
+ break;
+
+ sc_start4(ss, bl, type, 100, sg->skill_lv, sg->val1, sg->val2, 0, sg->limit);
+ break;
case UNT_TATAMIGAESHI:
case UNT_DEMONSTRATION:
skill->attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
@@ -12439,7 +12457,9 @@ int skill_unit_onleft(uint16 skill_id, struct block_list *bl, int64 tick) {
case DC_DONTFORGETME:
case DC_FORTUNEKISS:
case DC_SERVICEFORYOU:
- if ((battle_config.song_timer_reset && sce) || (!battle_config.song_timer_reset && sce && sce->val4 != 1)) {
+ if ((battle_config.song_timer_reset && sce) // athena style
+ || (!battle_config.song_timer_reset && sce && sce->val4 != 1)
+ ) {
timer->delete(sce->timer, status->change_timer);
//NOTE: It'd be nice if we could get the skill_lv for a more accurate extra time, but alas...
//not possible on our current implementation.
diff --git a/src/map/status.c b/src/map/status.c
index 23deca6fa..92c4ad3e0 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -12180,7 +12180,7 @@ int status_readdb(void)
sv->readdb(map->db_path, "pre-re/job_db1.txt", ',', 5+MAX_WEAPON_TYPE, 5+MAX_WEAPON_TYPE, -1, status->readdb_job1);
#endif
sv->readdb(map->db_path, "job_db2.txt", ',', 1, 1+MAX_LEVEL, -1, status->readdb_job2);
- sv->readdb(map->db_path, "size_fix.txt", ',', MAX_WEAPON_TYPE, MAX_WEAPON_TYPE, ARRAYLENGTH(status->atkmods), status->readdb_sizefix);
+ sv->readdb(map->db_path, DBPATH"size_fix.txt", ',', MAX_WEAPON_TYPE, MAX_WEAPON_TYPE, ARRAYLENGTH(status->atkmods), status->readdb_sizefix);
sv->readdb(map->db_path, DBPATH"refine_db.txt", ',', 4+MAX_REFINE, 4+MAX_REFINE, ARRAYLENGTH(status->refine_info), status->readdb_refine);
sv->readdb(map->db_path, "sc_config.txt", ',', 2, 2, SC_MAX, status->readdb_scconfig);