Cleaned up merge issues.
This commit is contained in:
commit
d3625e5c10
@ -27,6 +27,12 @@ homunculus_friendly_rate: 100
|
||||
// Can you name a homunculus more then once? (Note 1)
|
||||
hom_rename: no
|
||||
|
||||
// Minimum intimacy to evo the homunculus
|
||||
homunculus_evo_intimacy_need: 91100
|
||||
|
||||
// Reset intimacy after evolution to:
|
||||
homunculus_evo_intimacy_reset: 1000
|
||||
|
||||
// Intimacy needed to use Evolved Vanilmirth's Bio Explosion
|
||||
hvan_explosion_intimate: 45000
|
||||
|
||||
|
@ -205,4 +205,9 @@ char_moves_unlimited: no
|
||||
// Should we check if sql-tables are correct on server startup ?
|
||||
char_checkdb: yes
|
||||
|
||||
// Default map if character is in not-existing map when loaded.
|
||||
default_map: prontera
|
||||
default_map_x: 156
|
||||
default_map_y: 191
|
||||
|
||||
import: conf/import/char_conf.txt
|
||||
|
@ -626,6 +626,8 @@ bAddClassDropItemGroup 2071
|
||||
|
||||
bAddMaxWeight 2072
|
||||
bAddItemGroupHealRate 2073
|
||||
bHPVanishRaceRate 2074
|
||||
bSPVanishRaceRate 2075
|
||||
|
||||
EQI_HEAD_TOP 1
|
||||
EQI_ARMOR 2
|
||||
@ -4643,6 +4645,8 @@ BSF_REM_ON_LUXANIMA 0x040
|
||||
BSF_REM_ON_MADOGEAR 0x080
|
||||
BSF_REM_ON_DAMAGED 0x100
|
||||
BSF_PERMANENT 0x200
|
||||
BSF_FORCE_REPLACE 0x400
|
||||
BSF_FORCE_DUPLICATE 0x800
|
||||
|
||||
SKILL_PERM 0
|
||||
SKILL_TEMP 1
|
||||
|
@ -1,12 +1,12 @@
|
||||
// Homunculus Skill Tree Database
|
||||
//
|
||||
// Structure of Database:
|
||||
// Class,SkillID,MaxLv[,JobLevel],Prerequisite SkillID1,Prerequisite SkillLv1,PrereqSkillID2,PrereqSkillLv2,PrereqSkillID3,PrereqSkillLv3,PrereqSkillID4,PrereqSkillLv4,PrereqSkillID5,PrereqSkillLv5,IntimacyLvReq //SKILLNAME#Skill Name#
|
||||
// Class,SkillID,MaxLv,NeedLevel,Prerequisite SkillID1,Prerequisite SkillLv1,PrereqSkillID2,PrereqSkillLv2,PrereqSkillID3,PrereqSkillLv3,PrereqSkillID4,PrereqSkillLv4,PrereqSkillID5,PrereqSkillLv5,IntimacyLvReq //SKILLNAME#Skill Name#
|
||||
//
|
||||
// 01. Class Homunculus ID.
|
||||
// 02. SkillID Skill ID of the homunuculus skill.
|
||||
// 03. MaxLv Maximum level of the homunuculus skill.
|
||||
// 04. JobLevel Job level required for the skill to become available (optional, reserved, not used by server).
|
||||
// 04. NeedLevel Homunculus level required for the skill to become available
|
||||
// 05. Prerequisite SkillID Homunculus skill required for the skill to become available.
|
||||
// 06. Prerequisite SkillLv Level of the required homunculus skill.
|
||||
// ...
|
||||
@ -15,105 +15,105 @@
|
||||
// NOTE: MAX_PC_SKILL_REQUIRE (typically 5) ID/Lv pairs must be specified.
|
||||
|
||||
//Lif
|
||||
6001,8001,5,0,0,0,0,0,0,0,0,0,0,0 //HLIF_HEAL
|
||||
6001,8002,5,8001,3,0,0,0,0,0,0,0,0,0 //HLIF_AVOID
|
||||
6001,8003,5,8001,5,0,0,0,0,0,0,0,0,0 //HLIF_BRAIN
|
||||
6001,8001,5,0,0,0,0,0,0,0,0,0,0,0,0 //HLIF_HEAL
|
||||
6001,8002,5,0,8001,3,0,0,0,0,0,0,0,0,0 //HLIF_AVOID
|
||||
6001,8003,5,0,8001,5,0,0,0,0,0,0,0,0,0 //HLIF_BRAIN
|
||||
//Amistr
|
||||
6002,8005,5,0,0,0,0,0,0,0,0,0,0,0 //HAMI_CASTLE
|
||||
6002,8006,5,8005,5,0,0,0,0,0,0,0,0,0 //HAMI_DEFENCE
|
||||
6002,8007,5,8006,3,0,0,0,0,0,0,0,0,0 //HAMI_SKIN
|
||||
6002,8005,5,0,0,0,0,0,0,0,0,0,0,0,0 //HAMI_CASTLE
|
||||
6002,8006,5,0,8005,5,0,0,0,0,0,0,0,0,0 //HAMI_DEFENCE
|
||||
6002,8007,5,0,8006,3,0,0,0,0,0,0,0,0,0 //HAMI_SKIN
|
||||
//Filir
|
||||
6003,8009,5,0,0,0,0,0,0,0,0,0,0,0 //HFLI_MOON
|
||||
6003,8010,5,8009,3,0,0,0,0,0,0,0,0,0 //HFLI_FLEET
|
||||
6003,8011,5,8010,3,0,0,0,0,0,0,0,0,0 //HFLI_SPEED
|
||||
6003,8009,5,0,0,0,0,0,0,0,0,0,0,0,0 //HFLI_MOON
|
||||
6003,8010,5,0,8009,3,0,0,0,0,0,0,0,0,0 //HFLI_FLEET
|
||||
6003,8011,5,0,8010,3,0,0,0,0,0,0,0,0,0 //HFLI_SPEED
|
||||
//Vanilmirth
|
||||
6004,8013,5,0,0,0,0,0,0,0,0,0,0,0 //HVAN_CAPRICE
|
||||
6004,8014,5,8013,3,0,0,0,0,0,0,0,0,0 //HVAN_CHAOTIC
|
||||
6004,8015,5,8013,5,0,0,0,0,0,0,0,0,0 //HVAN_INSTRUCT
|
||||
6004,8013,5,0,0,0,0,0,0,0,0,0,0,0,0 //HVAN_CAPRICE
|
||||
6004,8014,5,0,8013,3,0,0,0,0,0,0,0,0,0 //HVAN_CHAOTIC
|
||||
6004,8015,5,0,8013,5,0,0,0,0,0,0,0,0,0 //HVAN_INSTRUCT
|
||||
//Lif2
|
||||
6005,8001,5,0,0,0,0,0,0,0,0,0,0,0 //HLIF_HEAL
|
||||
6005,8002,5,8001,3,0,0,0,0,0,0,0,0,0 //HLIF_AVOID
|
||||
6005,8003,5,8001,5,0,0,0,0,0,0,0,0,0 //HLIF_BRAIN
|
||||
6005,8001,5,0,0,0,0,0,0,0,0,0,0,0,0 //HLIF_HEAL
|
||||
6005,8002,5,0,8001,3,0,0,0,0,0,0,0,0,0 //HLIF_AVOID
|
||||
6005,8003,5,0,8001,5,0,0,0,0,0,0,0,0,0 //HLIF_BRAIN
|
||||
//Amistr2
|
||||
6006,8005,5,0,0,0,0,0,0,0,0,0,0,0 //HAMI_CASTLE
|
||||
6006,8006,5,8005,5,0,0,0,0,0,0,0,0,0 //HAMI_DEFENCE
|
||||
6006,8007,5,8006,3,0,0,0,0,0,0,0,0,0 //HAMI_SKIN
|
||||
6006,8005,5,0,0,0,0,0,0,0,0,0,0,0,0 //HAMI_CASTLE
|
||||
6006,8006,5,0,8005,5,0,0,0,0,0,0,0,0,0 //HAMI_DEFENCE
|
||||
6006,8007,5,0,8006,3,0,0,0,0,0,0,0,0,0 //HAMI_SKIN
|
||||
//Filir2
|
||||
6007,8009,5,0,0,0,0,0,0,0,0,0,0,0 //HFLI_MOON
|
||||
6007,8010,5,8009,3,0,0,0,0,0,0,0,0,0 //HFLI_FLEET
|
||||
6007,8011,5,8010,3,0,0,0,0,0,0,0,0,0 //HFLI_SPEED
|
||||
6007,8009,5,0,0,0,0,0,0,0,0,0,0,0,0 //HFLI_MOON
|
||||
6007,8010,5,0,8009,3,0,0,0,0,0,0,0,0,0 //HFLI_FLEET
|
||||
6007,8011,5,0,8010,3,0,0,0,0,0,0,0,0,0 //HFLI_SPEED
|
||||
//Vanilmirth2
|
||||
6008,8013,5,0,0,0,0,0,0,0,0,0,0,0 //HVAN_CAPRICE
|
||||
6008,8014,5,8013,3,0,0,0,0,0,0,0,0,0 //HVAN_CHAOTIC
|
||||
6008,8015,5,8013,5,0,0,0,0,0,0,0,0,0 //HVAN_INSTRUCT
|
||||
6008,8013,5,0,0,0,0,0,0,0,0,0,0,0,0 //HVAN_CAPRICE
|
||||
6008,8014,5,0,8013,3,0,0,0,0,0,0,0,0,0 //HVAN_CHAOTIC
|
||||
6008,8015,5,0,8013,5,0,0,0,0,0,0,0,0,0 //HVAN_INSTRUCT
|
||||
//Lif_H
|
||||
6009,8001,5,0,0,0,0,0,0,0,0,0,0,0 //HLIF_HEAL
|
||||
6009,8002,5,8001,3,0,0,0,0,0,0,0,0,0 //HLIF_AVOID
|
||||
6009,8003,5,8001,5,0,0,0,0,0,0,0,0,0 //HLIF_BRAIN
|
||||
6009,8004,3,0,0,0,0,0,0,0,0,0,0,910 //HLIF_CHANGE
|
||||
6009,8001,5,0,0,0,0,0,0,0,0,0,0,0,0 //HLIF_HEAL
|
||||
6009,8002,5,0,8001,3,0,0,0,0,0,0,0,0,0 //HLIF_AVOID
|
||||
6009,8003,5,0,8001,5,0,0,0,0,0,0,0,0,0 //HLIF_BRAIN
|
||||
6009,8004,3,0,0,0,0,0,0,0,0,0,0,0,910 //HLIF_CHANGE
|
||||
//Amistr_H
|
||||
6010,8005,5,0,0,0,0,0,0,0,0,0,0,0 //HAMI_CASTLE
|
||||
6010,8006,5,8005,5,0,0,0,0,0,0,0,0,0 //HAMI_DEFENCE
|
||||
6010,8007,5,8006,3,0,0,0,0,0,0,0,0,0 //HAMI_SKIN
|
||||
6010,8008,3,0,0,0,0,0,0,0,0,0,0,910 //HAMI_BLOODLUST
|
||||
6010,8005,5,0,0,0,0,0,0,0,0,0,0,0,0 //HAMI_CASTLE
|
||||
6010,8006,5,0,8005,5,0,0,0,0,0,0,0,0,0 //HAMI_DEFENCE
|
||||
6010,8007,5,0,8006,3,0,0,0,0,0,0,0,0,0 //HAMI_SKIN
|
||||
6010,8008,3,0,0,0,0,0,0,0,0,0,0,0,910 //HAMI_BLOODLUST
|
||||
//Filir_H
|
||||
6011,8009,5,0,0,0,0,0,0,0,0,0,0,0 //HFLI_MOON
|
||||
6011,8010,5,8009,3,0,0,0,0,0,0,0,0,0 //HFLI_FLEET
|
||||
6011,8011,5,8010,3,0,0,0,0,0,0,0,0,0 //HFLI_SPEED
|
||||
6011,8012,3,0,0,0,0,0,0,0,0,0,0,910 //HFLI_SBR44
|
||||
6011,8009,5,0,0,0,0,0,0,0,0,0,0,0,0 //HFLI_MOON
|
||||
6011,8010,5,0,8009,3,0,0,0,0,0,0,0,0,0 //HFLI_FLEET
|
||||
6011,8011,5,0,8010,3,0,0,0,0,0,0,0,0,0 //HFLI_SPEED
|
||||
6011,8012,3,0,0,0,0,0,0,0,0,0,0,0,910 //HFLI_SBR44
|
||||
//Vanilmirth_H
|
||||
6012,8013,5,0,0,0,0,0,0,0,0,0,0,0 //HVAN_CAPRICE
|
||||
6012,8014,5,8013,3,0,0,0,0,0,0,0,0,0 //HVAN_CHAOTIC
|
||||
6012,8015,5,8013,5,0,0,0,0,0,0,0,0,0 //HVAN_INSTRUCT
|
||||
6012,8016,3,0,0,0,0,0,0,0,0,0,0,910 //HVAN_EXPLOSION
|
||||
6012,8013,5,0,0,0,0,0,0,0,0,0,0,0,0 //HVAN_CAPRICE
|
||||
6012,8014,5,0,8013,3,0,0,0,0,0,0,0,0,0 //HVAN_CHAOTIC
|
||||
6012,8015,5,0,8013,5,0,0,0,0,0,0,0,0,0 //HVAN_INSTRUCT
|
||||
6012,8016,3,0,0,0,0,0,0,0,0,0,0,0,910 //HVAN_EXPLOSION
|
||||
//Lif2_H
|
||||
6013,8001,5,0,0,0,0,0,0,0,0,0,0,0 //HLIF_HEAL
|
||||
6013,8002,5,8001,3,0,0,0,0,0,0,0,0,0 //HLIF_AVOID
|
||||
6013,8003,5,8001,5,0,0,0,0,0,0,0,0,0 //HLIF_BRAIN
|
||||
6013,8004,3,0,0,0,0,0,0,0,0,0,0,910 //HLIF_CHANGE
|
||||
6013,8001,5,0,0,0,0,0,0,0,0,0,0,0,0 //HLIF_HEAL
|
||||
6013,8002,5,0,8001,3,0,0,0,0,0,0,0,0,0 //HLIF_AVOID
|
||||
6013,8003,5,0,8001,5,0,0,0,0,0,0,0,0,0 //HLIF_BRAIN
|
||||
6013,8004,3,0,0,0,0,0,0,0,0,0,0,0,910 //HLIF_CHANGE
|
||||
//Amistr2_H
|
||||
6014,8005,5,0,0,0,0,0,0,0,0,0,0,0 //HAMI_CASTLE
|
||||
6014,8006,5,8005,5,0,0,0,0,0,0,0,0,0 //HAMI_DEFENCE
|
||||
6014,8007,5,8006,3,0,0,0,0,0,0,0,0,0 //HAMI_SKIN
|
||||
6014,8008,3,0,0,0,0,0,0,0,0,0,0,910 //HAMI_BLOODLUST
|
||||
6014,8005,5,0,0,0,0,0,0,0,0,0,0,0,0 //HAMI_CASTLE
|
||||
6014,8006,5,0,8005,5,0,0,0,0,0,0,0,0,0 //HAMI_DEFENCE
|
||||
6014,8007,5,0,8006,3,0,0,0,0,0,0,0,0,0 //HAMI_SKIN
|
||||
6014,8008,3,0,0,0,0,0,0,0,0,0,0,0,910 //HAMI_BLOODLUST
|
||||
//Filir2_H
|
||||
6015,8009,5,0,0,0,0,0,0,0,0,0,0,0 //HFLI_MOON
|
||||
6015,8010,5,8009,3,0,0,0,0,0,0,0,0,0 //HFLI_FLEET
|
||||
6015,8011,5,8010,3,0,0,0,0,0,0,0,0,0 //HFLI_SPEED
|
||||
6015,8012,3,0,0,0,0,0,0,0,0,0,0,910 //HFLI_SBR44
|
||||
6015,8009,5,0,0,0,0,0,0,0,0,0,0,0,0 //HFLI_MOON
|
||||
6015,8010,5,0,8009,3,0,0,0,0,0,0,0,0,0 //HFLI_FLEET
|
||||
6015,8011,5,0,8010,3,0,0,0,0,0,0,0,0,0 //HFLI_SPEED
|
||||
6015,8012,3,0,0,0,0,0,0,0,0,0,0,0,910 //HFLI_SBR44
|
||||
//Vanilmirth2_H
|
||||
6016,8013,5,0,0,0,0,0,0,0,0,0,0,0 //HVAN_CAPRICE
|
||||
6016,8014,5,8013,3,0,0,0,0,0,0,0,0,0 //HVAN_CHAOTIC
|
||||
6016,8015,5,8013,5,0,0,0,0,0,0,0,0,0 //HVAN_INSTRUCT
|
||||
6016,8016,3,0,0,0,0,0,0,0,0,0,0,910 //HVAN_EXPLOSION
|
||||
6016,8013,5,0,0,0,0,0,0,0,0,0,0,0,0 //HVAN_CAPRICE
|
||||
6016,8014,5,0,8013,3,0,0,0,0,0,0,0,0,0 //HVAN_CHAOTIC
|
||||
6016,8015,5,0,8013,5,0,0,0,0,0,0,0,0,0 //HVAN_INSTRUCT
|
||||
6016,8016,3,0,0,0,0,0,0,0,0,0,0,0,910 //HVAN_EXPLOSION
|
||||
//Eira
|
||||
6048,8022,5,0,0,0,0,0,0,0,0,0,0,0 //MH_LIGHT_OF_REGENE
|
||||
6048,8023,5,0,0,0,0,0,0,0,0,0,0,0 //MH_OVERED_BOOST
|
||||
6048,8024,5,0,0,0,0,0,0,0,0,0,0,0 //MH_ERASER_CUTTER
|
||||
6048,8025,5,0,0,0,0,0,0,0,0,0,0,0 //MH_XENO_SLASHER
|
||||
6048,8026,5,0,0,0,0,0,0,0,0,0,0,0 //MH_SILENT_BREEZE
|
||||
6048,8022,5,128,0,0,0,0,0,0,0,0,0,0,0 //MH_LIGHT_OF_REGENE
|
||||
6048,8023,5,114,0,0,0,0,0,0,0,0,0,0,0 //MH_OVERED_BOOST
|
||||
6048,8024,5,106,0,0,0,0,0,0,0,0,0,0,0 //MH_ERASER_CUTTER
|
||||
6048,8025,5,121,0,0,0,0,0,0,0,0,0,0,0 //MH_XENO_SLASHER
|
||||
6048,8026,5,137,0,0,0,0,0,0,0,0,0,0,0 //MH_SILENT_BREEZE
|
||||
//Bayeri
|
||||
6049,8031,5,0,0,0,0,0,0,0,0,0,0,0 //MH_STAHL_HORN
|
||||
6049,8032,5,0,0,0,0,0,0,0,0,0,0,0 //MH_GOLDENE_FERSE
|
||||
6049,8033,5,0,0,0,0,0,0,0,0,0,0,0 //MH_STEINWAND
|
||||
6049,8034,5,0,0,0,0,0,0,0,0,0,0,0 //MH_HEILIGE_STANGE
|
||||
6049,8035,5,0,0,0,0,0,0,0,0,0,0,0 //MH_ANGRIFFS_MODUS
|
||||
6049,8031,5,105,0,0,0,0,0,0,0,0,0,0,0 //MH_STAHL_HORN
|
||||
6049,8032,5,112,0,0,0,0,0,0,0,0,0,0,0 //MH_GOLDENE_FERSE
|
||||
6049,8033,5,121,0,0,0,0,0,0,0,0,0,0,0 //MH_STEINWAND
|
||||
6049,8034,5,138,0,0,0,0,0,0,0,0,0,0,0 //MH_HEILIGE_STANGE
|
||||
6049,8035,5,130,0,0,0,0,0,0,0,0,0,0,0 //MH_ANGRIFFS_MODUS
|
||||
//Sera
|
||||
6050,8018,5,0,0,0,0,0,0,0,0,0,0,0 //MH_SUMMON_LEGION
|
||||
6050,8019,5,0,0,0,0,0,0,0,0,0,0,0 //MH_NEEDLE_OF_PARALYZE
|
||||
6050,8020,5,0,0,0,0,0,0,0,0,0,0,0 //MH_POISON_MIST
|
||||
6050,8021,5,0,0,0,0,0,0,0,0,0,0,0 //MH_PAIN_KILLER
|
||||
6050,8018,5,132,0,0,0,0,0,0,0,0,0,0,0 //MH_SUMMON_LEGION
|
||||
6050,8019,5,105,0,0,0,0,0,0,0,0,0,0,0 //MH_NEEDLE_OF_PARALYZE
|
||||
6050,8020,5,116,0,0,0,0,0,0,0,0,0,0,0 //MH_POISON_MIST
|
||||
6050,8021,5,123,0,0,0,0,0,0,0,0,0,0,0 //MH_PAIN_KILLER
|
||||
//Dieter
|
||||
6051,8039,5,0,0,0,0,0,0,0,0,0,0,0 //MH_MAGMA_FLOW
|
||||
6051,8040,5,0,0,0,0,0,0,0,0,0,0,0 //MH_GRANITIC_ARMOR
|
||||
6051,8041,5,0,0,0,0,0,0,0,0,0,0,0 //MH_LAVA_SLIDE
|
||||
6051,8042,5,0,0,0,0,0,0,0,0,0,0,0 //MH_PYROCLASTIC
|
||||
6051,8043,5,0,0,0,0,0,0,0,0,0,0,0 //MH_VOLCANIC_ASH
|
||||
6051,8039,5,122,0,0,0,0,0,0,0,0,0,0,0 //MH_MAGMA_FLOW
|
||||
6051,8040,5,116,0,0,0,0,0,0,0,0,0,0,0 //MH_GRANITIC_ARMOR
|
||||
6051,8041,5,109,0,0,0,0,0,0,0,0,0,0,0 //MH_LAVA_SLIDE
|
||||
6051,8042,5,131,0,0,0,0,0,0,0,0,0,0,0 //MH_PYROCLASTIC
|
||||
6051,8043,5,102,0,0,0,0,0,0,0,0,0,0,0 //MH_VOLCANIC_ASH
|
||||
//Elanor
|
||||
6052,8027,1,0,0,0,0,0,0,0,0,0,0,0 //MH_STYLE_CHANGE
|
||||
6052,8028,5,0,0,0,0,0,0,0,0,0,0,0 //MH_SONIC_CRAW
|
||||
6052,8029,5,0,0,0,0,0,0,0,0,0,0,0 //MH_SILVERVEIN_RUSH
|
||||
6052,8030,5,0,0,0,0,0,0,0,0,0,0,0 //MH_MIDNIGHT_FRENZY
|
||||
6052,8036,5,0,0,0,0,0,0,0,0,0,0,0 //MH_TINDER_BREAKER
|
||||
6052,8037,5,0,0,0,0,0,0,0,0,0,0,0 //MH_CBC
|
||||
6052,8038,5,0,0,0,0,0,0,0,0,0,0,0 //MH_EQC
|
||||
6052,8027,1,100,0,0,0,0,0,0,0,0,0,0,0 //MH_STYLE_CHANGE
|
||||
6052,8028,5,100,0,0,0,0,0,0,0,0,0,0,0 //MH_SONIC_CRAW
|
||||
6052,8029,5,114,0,0,0,0,0,0,0,0,0,0,0 //MH_SILVERVEIN_RUSH
|
||||
6052,8030,5,128,0,0,0,0,0,0,0,0,0,0,0 //MH_MIDNIGHT_FRENZY
|
||||
6052,8036,5,100,0,0,0,0,0,0,0,0,0,0,0 //MH_TINDER_BREAKER
|
||||
6052,8037,5,112,0,0,0,0,0,0,0,0,0,0,0 //MH_CBC
|
||||
6052,8038,5,133,0,0,0,0,0,0,0,0,0,0,0 //MH_EQC
|
||||
|
@ -1,12 +1,12 @@
|
||||
// Homunculus Skill Tree Database
|
||||
//
|
||||
// Structure of Database:
|
||||
// Class,SkillID,MaxLv[,JobLevel],Prerequisite SkillID1,Prerequisite SkillLv1,PrereqSkillID2,PrereqSkillLv2,PrereqSkillID3,PrereqSkillLv3,PrereqSkillID4,PrereqSkillLv4,PrereqSkillID5,PrereqSkillLv5,IntimacyLvReq //SKILLNAME#Skill Name#
|
||||
// Class,SkillID,MaxLv,NeedLevel,Prerequisite SkillID1,Prerequisite SkillLv1,PrereqSkillID2,PrereqSkillLv2,PrereqSkillID3,PrereqSkillLv3,PrereqSkillID4,PrereqSkillLv4,PrereqSkillID5,PrereqSkillLv5,IntimacyLvReq //SKILLNAME#Skill Name#
|
||||
//
|
||||
// 01. Class Homunculus ID.
|
||||
// 02. SkillID Skill ID of the homunuculus skill.
|
||||
// 03. MaxLv Maximum level of the homunuculus skill.
|
||||
// 04. JobLevel Job level required for the skill to become available (optional, reserved, not used by server).
|
||||
// 04. NeedLevel Homunculus level required for the skill to become available
|
||||
// 05. Prerequisite SkillID Homunculus skill required for the skill to become available.
|
||||
// 06. Prerequisite SkillLv Level of the required homunculus skill.
|
||||
// ...
|
||||
|
@ -126,13 +126,13 @@
|
||||
2371:2523,{ bonus bAgi,5; bonus bFlee,10; }
|
||||
2374:2729,{ bonus2 bAddClass,Class_All,3; bonus bMatkRate,3; }
|
||||
2375:2729,{ bonus2 bAddClass,Class_All,3; bonus bMatkRate,3; }
|
||||
2376:2435:2538,{ bonus2 bSubRace,RC_All,-300; bonus2 bSubRace,RC_DemiHuman,300; bonus2 bSubRace,RC_Player,300; bonus bVit,3; bonus bMaxHPRate,12; bonus bHealpower2,10; bonus bAddItemHealRate,10; autobonus2 "{ bonus2 bHPRegenRate,600,1000; }",5,10000,BF_WEAPON,"{ specialeffect2 EF_HEAL; }"; }
|
||||
2377:2435:2538,{ bonus2 bSubRace,RC_All,-300; bonus2 bSubRace,RC_DemiHuman,300; bonus2 bSubRace,RC_Player,300; bonus bStr,3; bonus bMaxHPRate,12; bonus2 bSkillAtk,"MC_MAMMONITE",20; bonus2 bSkillHeal,"AM_POTIONPITCHER",10; bonus2 bSkillHeal2,"AM_POTIONPITCHER",10; bonus2 bSkillHeal2,"AL_HEAL",10; bonus bUnbreakableArmor,0; }
|
||||
2378:2435:2538,{ bonus2 bSubRace,RC_All,-300; bonus2 bSubRace,RC_DemiHuman,300; bonus2 bSubRace,RC_Player,300; bonus bAgi,3; bonus bMaxHPRate,12; bonus bCritical,5; bonus bAspdRate,5; autobonus "{ bonus2 bHPRegenRate,300,1000; }",10,10000,BF_WEAPON,"{ specialeffect2 EF_HEAL; }"; }
|
||||
2379:2436:2539,{ bonus2 bSubRace,RC_All,-300; bonus2 bSubRace,RC_DemiHuman,300; bonus2 bSubRace,RC_Player,300; bonus bInt,3; bonus bMaxHPRate,12; bonus2 bResEff,Eff_Stun,2000; autobonus2 "{ bonus bDefEle,Ele_Ghost; }",30,10000,BF_WEAPON,"{ specialeffect2 EF_ENERGYCOAT; }"; }
|
||||
2380:2436:2539,{ bonus2 bSubRace,RC_All,-300; bonus2 bSubRace,RC_DemiHuman,300; bonus2 bSubRace,RC_Player,300; bonus bInt,3; bonus bMaxHPRate,12; bonus2 bVariableCastrate,"AL_HOLYLIGHT",-50; bonus bHealPower,6; autobonus2 "{ bonus bDefEle,Ele_Ghost; }",30,10000,BF_WEAPON,"{ specialeffect2 EF_ENERGYCOAT; }"; }
|
||||
2381:2436:2539,{ bonus2 bSubRace,RC_All,-300; bonus2 bSubRace,RC_DemiHuman,300; bonus2 bSubRace,RC_Player,300; bonus bDex,3; bonus bMaxHPRate,12; bonus bLongAtkDef,10; bonus bDelayRate,-25; }
|
||||
2382:2437:2540,{ bonus2 bSubRace,RC_All,-300; bonus2 bSubRace,RC_DemiHuman,300; bonus2 bSubRace,RC_Player,300; bonus bDex,3; bonus bMaxHPRate,12; bonus bLongAtkDef,10; bonus bDelayRate,-25; }
|
||||
2376:2435:2538,{ bonus2 bSubRace,RC_All,-200; bonus2 bSubRace,RC_DemiHuman,200; bonus2 bSubRace,RC_Player,200; bonus bVit,3; bonus bMaxHPRate,12; bonus bHealpower2,10; bonus bAddItemHealRate,10; autobonus2 "{ bonus2 bHPRegenRate,600,1000; }",5,10000,BF_WEAPON,"{ specialeffect2 EF_HEAL; }"; }
|
||||
2377:2435:2538,{ bonus2 bSubRace,RC_All,-200; bonus2 bSubRace,RC_DemiHuman,200; bonus2 bSubRace,RC_Player,200; bonus bStr,3; bonus bMaxHPRate,12; bonus2 bSkillAtk,"MC_MAMMONITE",20; bonus2 bSkillHeal,"AM_POTIONPITCHER",10; bonus2 bSkillHeal2,"AM_POTIONPITCHER",10; bonus2 bSkillHeal2,"AL_HEAL",10; bonus bUnbreakableArmor,0; }
|
||||
2378:2435:2538,{ bonus2 bSubRace,RC_All,-200; bonus2 bSubRace,RC_DemiHuman,200; bonus2 bSubRace,RC_Player,200; bonus bAgi,3; bonus bMaxHPRate,12; bonus bCritical,5; bonus bAspdRate,5; autobonus "{ bonus2 bHPRegenRate,300,1000; }",10,10000,BF_WEAPON,"{ specialeffect2 EF_HEAL; }"; }
|
||||
2379:2436:2539,{ bonus2 bSubRace,RC_All,-200; bonus2 bSubRace,RC_DemiHuman,200; bonus2 bSubRace,RC_Player,200; bonus bInt,3; bonus bMaxHPRate,12; bonus2 bResEff,Eff_Stun,2000; autobonus2 "{ bonus bDefEle,Ele_Ghost; }",30,10000,BF_WEAPON,"{ specialeffect2 EF_ENERGYCOAT; }"; }
|
||||
2380:2436:2539,{ bonus2 bSubRace,RC_All,-200; bonus2 bSubRace,RC_DemiHuman,200; bonus2 bSubRace,RC_Player,200; bonus bInt,3; bonus bMaxHPRate,12; bonus2 bVariableCastrate,"AL_HOLYLIGHT",-50; bonus bHealPower,6; autobonus2 "{ bonus bDefEle,Ele_Ghost; }",30,10000,BF_WEAPON,"{ specialeffect2 EF_ENERGYCOAT; }"; }
|
||||
2381:2436:2539,{ bonus2 bSubRace,RC_All,-200; bonus2 bSubRace,RC_DemiHuman,200; bonus2 bSubRace,RC_Player,200; bonus bDex,3; bonus bMaxHPRate,12; bonus bLongAtkDef,10; bonus bDelayRate,-25; }
|
||||
2382:2437:2540,{ bonus2 bSubRace,RC_All,-200; bonus2 bSubRace,RC_DemiHuman,200; bonus2 bSubRace,RC_Player,200; bonus bDex,3; bonus bMaxHPRate,12; bonus bLongAtkDef,10; bonus bDelayRate,-25; }
|
||||
2387:2440:2744,{ bonus bMaxHPrate,7; bonus bMaxSPrate,7; bonus bVariableCastrate,-3; bonus bDelayrate,-15; }
|
||||
2390:2749,{ bonus bFlee2,5; }
|
||||
2394:2444:2549,{ bonus2 bAddClass,Class_All,5; bonus bMatkRate,5; bonus2 bResEff,Eff_Freeze,10000; bonus2 bSkillHeal2,"AM_POTIONPITCHER",3; bonus2 bSkillHeal2,"AL_HEAL",3; bonus2 bSkillHeal2,"PR_SANCTUARY",3; }
|
||||
|
@ -646,7 +646,7 @@
|
||||
1291,Guillotine_Katar,Guillotine Katar,5,56000,,1500,200,,1,1,0x00001000,63,2,34,4,140,1,16,{ bonus bDex,2; bonus bFlee,-30; bonus2 bAddRace,RC_DemiHuman,50; bonus2 bAddRace,RC_Player,50; bonus2 bSkillAtk,"GC_CROSSIMPACT",30; },{},{}
|
||||
1292,Upg_Katar,Upg Katar,5,20,,1000,80,,1,1,0x00001000,63,2,34,3,1,1,16,{ bonus bBaseAtk,(getrefine()*10); bonus bCritAtkRate,(getrefine()*2); if(BaseLevel>70) bonus bBaseAtk,(((BaseLevel-70)/10)*10); },{},{}
|
||||
1293,Velum_Jamadhar,Vellum Jamadhar,5,20,,1200,170,,1,0,0x00001000,63,2,34,4,95,1,16,{ bonus4 bSetDefRace,RC_Player,10000,5000,1; bonus4 bSetMDefRace,RC_Player,10000,5000,1; bonus bAspdRate,getrefine(); },{},{}
|
||||
1294,Velum_Scare,Vellum Scale,5,20,,1200,50,,1,0,0x00001000,63,2,34,4,95,1,16,{ bonus2 bSPVanishRate,10000,10; },{},{}
|
||||
1294,Velum_Scare,Vellum Scale,5,20,,1200,50,,1,0,0x00001000,63,2,34,4,95,1,16,{ bonus3 bSPVanishRaceRate,RC_Player,10000,10; },{},{}
|
||||
1295,Blood_Tears_,Blood Tears,5,20,,1700,120,,1,1,0x00001000,18,2,34,4,55,1,16,{},{},{}
|
||||
1296,Metal_Katar,Metal Katar,5,20,,0,75,,1,1,0x00001000,63,2,34,3,1,1,16,{ bonus bBaseAtk,(getrefine()*5); bonus bCritAtkRate,getrefine(); set .@i,((BaseLevel/10)>12)?12:(BaseLevel/10); if(.@i>2) bonus bBaseAtk,((.@i-2)*5); },{},{}
|
||||
//
|
||||
@ -716,7 +716,7 @@
|
||||
1392,Ygnus_Stale,Ignus Steel,5,56000,,1900,250,,1,1,0x000444A2,63,2,34,4,95,1,7,{ bonus bAtkEle,Ele_Fire; bonus bUnbreakableWeapon,0; },{},{}
|
||||
1393,End_Sektura,End Sectora,5,56000,,1900,250,,1,1,0x000444A2,63,2,34,4,95,1,7,{ bonus bAtkEle,Ele_Water; bonus bUnbreakableWeapon,0; },{},{}
|
||||
1394,Upg_Two_Handed_Axe,Upg Two Handed Axe,5,20,,2000,110,,1,1,0x000444A2,63,2,34,3,1,1,7,{ bonus bBaseAtk,(getrefine()*14); if(BaseLevel>70) bonus bBaseAtk,(((BaseLevel-70)/10)*10); },{},{}
|
||||
1395,Velum_Buster,Vellum Buster,5,20,,2500,50,,1,0,0x000444A2,63,2,34,4,95,1,7,{ bonus bUnbreakableWeapon,0; bonus2 bSPVanishRate,10000,10; },{},{}
|
||||
1395,Velum_Buster,Vellum Buster,5,20,,2500,50,,1,0,0x000444A2,63,2,34,4,95,1,7,{ bonus bUnbreakableWeapon,0; bonus3 bSPVanishRaceRate,RC_Player,10000,10; },{},{}
|
||||
1396,Velum_Guillotine,Vellum Guillotine,5,20,,5500,300,,1,0,0x000444A2,63,2,34,4,95,1,7,{ bonus bUnbreakableWeapon,0; bonus2 bAddRace,RC_Player,40; bonus2 bIgnoreDefRaceRate,RC_Player,30; if(getrefine()>=6) { bonus2 bSkillAtk,"NC_AXEBOOMERANG",80; bonus2 bSkillAtk,"NC_POWERSWING",80; } if(getrefine()>=9) { bonus2 bAddRace,RC_Player,60; } },{},{}
|
||||
1397,Bradium_Stonehammer_,Bradium Stonehammer,5,20,,2700,210,,1,2,0x000444A2,63,2,34,4,75,1,7,{ bonus bUnbreakableWeapon,0; },{},{}
|
||||
1398,Metal_Two_Handed_Axe,Metal Two Handed Axe,5,20,,0,105,,1,1,0x000444A2,63,2,34,3,1,1,7,{ bonus bUnbreakableWeapon,0; bonus bBaseAtk,(getrefine()*7); set .@i,((BaseLevel/10)>12)?12:(BaseLevel/10); if(.@i>2) bonus bBaseAtk,((.@i-2)*5); },{},{}
|
||||
@ -8943,7 +8943,7 @@
|
||||
18110,Big_CrossBow,Giant Crossbow,5,56000,,900,160,,5,2,0x00000800,63,2,34,4,110,1,11,{ bonus2 bSkillAtk,"RA_ARROWSTORM",(getrefine()*5); bonus2 bSkillUseSP,"RA_ARROWSTORM",(getrefine()*5); if(readparam(bAgi)>=120){ bonus bAspd,1; } },{},{}
|
||||
18111,Creeper_Bow,Creeper Bow,5,56000,,1500,150,,5,2,0x00080800,63,2,34,3,120,1,11,{ bonus bDex,1; bonus3 bAutoSpell,"PF_SPIDERWEB",1,200; },{},{}
|
||||
18112,Upg_Bow,Upg Bow,5,20,,600,60,,5,1,0x000A0848,63,2,34,3,1,0,11,{ bonus bBaseAtk,(getrefine()*7); bonus bLongAtkRate,(getrefine()*2); if(BaseJob==Job_Hunter) bonus bBaseAtk,20; if(BaseLevel>70) bonus bBaseAtk,(((BaseLevel-70)/10)*10); },{},{}
|
||||
18113,Velum_Arbalest,Vellum Arbalest,5,20,,1100,50,,5,0,0x000A0848,63,2,34,4,95,1,11,{ bonus2 bSPVanishRate,10000,4; bonus bAspd,-5; },{},{}
|
||||
18113,Velum_Arbalest,Vellum Arbalest,5,20,,1100,50,,5,0,0x000A0848,63,2,34,4,95,1,11,{ bonus3 bSPVanishRaceRate,RC_Player,10000,4; bonus bAspd,-5; },{},{}
|
||||
18114,Velum_CrossBow,Vellum CrossBow,5,20,,1100,110,,5,0,0x000A0848,63,2,34,4,95,1,11,{ bonus2 bAddRace,RC_Player,30+getrefine(); bonus2 bIgnoreDefRaceRate,RC_Player,30; },{},{}
|
||||
18115,Orc_Archer_Bow_,Orc Archer Bow,5,20,,1600,120,,5,1,0x000A0848,63,2,34,3,65,1,11,{},{},{}
|
||||
18116,Metal_Bow,Metal Bow,5,20,,0,50,,5,1,0x00080800,63,2,34,3,1,1,11,{ if(BaseJob==Job_Hunter && Upper!=2) bonus bBaseAtk,10; bonus bBaseAtk,(getrefine()*3); bonus bLongAtkRate,getrefine(); set .@i,((BaseLevel/10)>12)?12:(BaseLevel/10); if(.@i>2) bonus bBaseAtk,((.@i-2)*5); },{},{}
|
||||
@ -9691,7 +9691,7 @@
|
||||
// More 2-Handed Swords
|
||||
21000,Upg_Twohand_Sword,Upg Two-Handed Sword,5,20,,1500,100,,1,1,0x00004082,63,2,34,3,1,1,3,{ bonus bBaseAtk,(getrefine()*12); bonus bMatk,(getrefine()*5); if(BaseLevel>70) bonus bBaseAtk,(((BaseLevel-70)/10)*10); },{},{}
|
||||
21001,Velum_Claymore,Vellum Claymore,5,20,,3500,260,,1,0,0x00004082,63,2,34,4,95,1,3,{ bonus2 bAddRace,RC_Player,80; bonus2 bIgnoreDefRaceRate,RC_Player,30; if(getrefine()>=6) { bonus2 bAddRace,RC_Player,40; } if(getrefine()>=9) { autobonus2 "{ bonus bShortWeaponDamageReturn,20; bonus bMagicDamageReturn,20; }",6000,2000,BF_WEAPON,"{ specialeffect2 EF_REFLECTSHIELD; }"; } },{},{}
|
||||
21002,Velum_Katzbalger,Vellum Katzbalger,5,20,,2500,100,,1,0,0x00004082,63,2,34,4,95,1,3,{ bonus2 bHPVanishRate,10000,8; },{},{}
|
||||
21002,Velum_Katzbalger,Vellum Katzbalger,5,20,,2500,100,,1,0,0x00004082,63,2,34,4,95,1,3,{ bonus3 bHPVanishRaceRate,RC_Player,10000,8; },{},{}
|
||||
21003,Muramasa_,Muramasa,5,20,,1000,155,,1,2,0x00004082,63,2,34,4,48,1,3,{},{},{}
|
||||
21004,Alca_Bringer_,Alca Bringer,5,20,,3400,280,,2,2,0x00004082,63,2,34,3,100,1,3,{},{},{}
|
||||
21005,Metal_Two_Hand_Sword,Metal Two Hand Sword,5,20,,0,95,,1,1,0x00004082,63,2,34,3,1,1,3,{ bonus bBaseAtk,(getrefine()*6); bonus bMatk,(getrefine()*2); set .@i,((BaseLevel/10)>12)?12:(BaseLevel/10); if(.@i>2) bonus bBaseAtk,((.@i-2)*5); },{},{}
|
||||
@ -9878,10 +9878,10 @@
|
||||
22837,Integer_Time,Integer Time,2,10,,100,,,,,,,,,,,,,{ getitem 673,5; },{},{}
|
||||
22838,Something_Present_Candy_Holders,Something Present Candy Holders,2,10,,100,,,,,,,,,,,,,{},{},{}
|
||||
22842,Sealed_Dracula_Scroll_II,Sealed Dracula Scroll II,2,10,,10,,,,,,,,,,,,,{ getitem callfunc("F_Rand",22846,6228,6232,24223,24227,17474/*, Enchant Letter*/),1; },{},{}
|
||||
22843,Superstar_Snack,Superstar Snack,2,10,,10,,,,,,,,,,,,,{ bonus_script "{ bonus bAtk2,50; bonus bMatk,50; }",300; },{},{}
|
||||
22843,Superstar_Snack,Superstar Snack,2,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ bonus_script "{ bonus bAtk2,50; bonus bMatk,50; }",300; },{},{}
|
||||
22844,Sealed_Dracula_Card_Album,Sealed Dracula Card Album,2,10,,10,,,,,,,,,,,,,{/*No Info*/},{},{}
|
||||
22845,Sealed_Fortune_Egg,Sealed Fortune Egg,2,10,,10,,,,,,,,,,,,,{ getitem callfunc("F_Rand",4488,4497,4486,4480,4485,4539,4487,4494,4538,4489,4490,4482,4503,22846),1; },{},{}
|
||||
22846,Sealed_Dracula_Card,Sealed Dracula Card,2,10,,10,,,,,,,,,,,,,{ bonus_script "{ bonus3 bSPDrainRate,50,5,0; }",300; },{},{}
|
||||
22846,Sealed_Dracula_Card,Sealed Dracula Card,2,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ bonus_script "{ bonus3 bSPDrainRate,50,5,0; }",300; },{},{}
|
||||
// Shadow Equip
|
||||
24000,T_STR1_Armor_Shadow,T STR1 Armor Shadow,12,10,,0,,,,0,0xFFFFFFFF,63,2,65536,,1,,,{ bonus bStr,1; },{},{}
|
||||
24001,T_DEX1_Weapon_Shadow,T DEX1 Weapon Shadow,12,10,,0,,,,0,0xFFFFFFFF,63,2,131072,,1,,,{ bonus bDex,1; },{},{}
|
||||
|
@ -333,8 +333,11 @@ bonus2 bSPDrainRate,n,x; Adds a n/10% chance to drain x% SP when attacking
|
||||
bonus3 bSPDrainRate,n,x,y; Adds a n/10% chance to either gain SP equivalent to x% of damage dealt, OR drain the amount of SP from the enemy
|
||||
(y: 0=gain SP, 1=drain SP from target)
|
||||
|
||||
bonus2 bHPVanishRate,n,x; Add a n/10% chance of decreasing enemy's HP (player) amount by x% when attacking
|
||||
bonus2 bSPVanishRate,n,x; Add a n/10% chance of decreasing enemy's SP (player) amount by x% when attacking
|
||||
bonus2 bHPVanishRate,n,x; Add a n/100% chance of decreasing enemy's HP amount by x% when attacking
|
||||
bonus2 bSPVanishRate,n,x; Add a n/100% chance of decreasing enemy's SP amount by x% when attacking
|
||||
|
||||
bonus3 bHPVanishRaceRate,r,n,x; Add a n/100% chance of decreasing enemy's HP amount by x% when attacking, depends on enemy race r
|
||||
bonus3 bSPVanishRaceRate,r,n,x; Add a n/100% chance of decreasing enemy's SP amount by x% when attacking, depends on enemy race r
|
||||
|
||||
bonus2 bHPGainRaceAttack,r,n; Heals +n HP on every hit when attacking an enemy of race r
|
||||
bonus2 bSPGainRaceAttack,r,n; Heals +n SP on every hit when attacking an enemy of race r
|
||||
|
@ -2176,15 +2176,19 @@ Currently the max packet size is 0xFFFF (see 'WFIFOSET()' in 'src/common/socket.
|
||||
- chrif_connectack
|
||||
|
||||
0x2afb
|
||||
Type: AZ
|
||||
Structure: <cmd>.W <?>.B
|
||||
index: 0,2
|
||||
len: variable: 3+NAME_LENGTH
|
||||
Type: HZ
|
||||
Structure: <cmd>.W <size>.W <status>.B <servername>.?B <defaultmap>.?B <mapx>.W <mapy>.W
|
||||
index: 0,2,4,5+NAME_LENGTH,5+NAME_LENGTH+MAP_NAME_LENGTH,5+NAME_LENGTH+MAP_NAME_LENGTH+2
|
||||
len: variable: 9+NAME_LENGTH+MAP_NAME_LENGTH
|
||||
parameter:
|
||||
- cmd : packet identification (0x2afb)
|
||||
- ?
|
||||
- status : 0 Success, 1 : Fail
|
||||
- servername :
|
||||
- defaultmap :
|
||||
- mapx :
|
||||
- mapy :
|
||||
desc:
|
||||
- send name for wisp to player
|
||||
- Map received from map-server, then send reply with server name and default map
|
||||
|
||||
0x2afd
|
||||
Type: AZ
|
||||
@ -2491,9 +2495,9 @@ Currently the max packet size is 0xFFFF (see 'WFIFOSET()' in 'src/common/socket.
|
||||
|
||||
0x2b2f
|
||||
Type: AZ
|
||||
Structure: <cmd>.W <len>.W <cid>.L <count>.W
|
||||
Structure: <cmd>.W <len>.W <cid>.L <count>.B { <bonus_script_data>.?B }
|
||||
index: 0,2,4,8
|
||||
len: variable: 10+50*bonus_script_data
|
||||
len: variable: 9+count*bonus_script_data
|
||||
parameter:
|
||||
- cmd : packet identification (0x2b2f)
|
||||
desc:
|
||||
@ -2840,9 +2844,9 @@ Currently the max packet size is 0xFFFF (see 'WFIFOSET()' in 'src/common/socket.
|
||||
|
||||
0x2b2e
|
||||
Type: ZA
|
||||
Structure: <cmd>.W <len>.W <char_id>.L <count>.W
|
||||
Structure: <cmd>.W <len>.W <char_id>.L <count>.B { <bonus_script_data>.?B }
|
||||
index: 0,2,4,8
|
||||
len: variable: 10+MAX_PC_BONUS_SCRIPT*bonus_script_data
|
||||
len: variable: 9+count*bonus_script_data
|
||||
parameter:
|
||||
- cmd : packet identification (0x2b2e)
|
||||
- len
|
||||
|
@ -5350,9 +5350,6 @@ After that time, the script will automatically expire. The same bonus cannot be
|
||||
stacked. By default, this bonus will be stored on `bonus_script` table when player
|
||||
logs out.
|
||||
|
||||
Note that the maximum number of 'bonus_script' commands that can run simultaneously
|
||||
for a player is 10 (MAX_PC_BONUS_SCRIPT in 'src/map/pc.h').
|
||||
|
||||
Flags (bitmask):
|
||||
1 : Remove when dead.
|
||||
2 : Removable by Dispell.
|
||||
@ -5360,10 +5357,13 @@ Flags (bitmask):
|
||||
8 : Remove when player logs out.
|
||||
16 : Removeable by Banishing Buster.
|
||||
32 : Removable by Refresh.
|
||||
128 : Removable by Luxanima.
|
||||
256 : Remove when Madogear is activated or deactivated.
|
||||
512 : Remove when receive damage.
|
||||
1024: Script is permanent, cannot be cleared by bonus_script_clear
|
||||
64 : Removable by Luxanima.
|
||||
128 : Remove when Madogear is activated or deactivated.
|
||||
256 : Remove when receive damage.
|
||||
512 : Script is permanent, cannot be cleared by bonus_script_clear.
|
||||
1024: Force to replace duplicated script by expanding the duration.
|
||||
2048: Force to add duplicated script. This flag cannot be stacked with 1024,
|
||||
if both are defined, 1024 will be checked first and ignore this flag.
|
||||
|
||||
Types:
|
||||
This will be used to decide negative or positive buff for 'debuff_on_logout'.
|
||||
|
@ -91,27 +91,27 @@ OnInit:
|
||||
|
||||
OnMenu:
|
||||
set .@size, getarraysize(@i);
|
||||
if (!.@size) set .@i, select(.menu$);
|
||||
else if (.@size == 1) set .@i, @i[0];
|
||||
if (!.@size) set @shop_index, select(.menu$);
|
||||
else if (.@size == 1) set @shop_index, @i[0];
|
||||
else {
|
||||
for(set .@j,0; .@j<.@size; set .@j,.@j+1)
|
||||
set .@menu$, .@menu$+.Shops$[@i[.@j]]+":";
|
||||
set .@i, @i[select(.@menu$)-1];
|
||||
set @shop_index, @i[select(.@menu$)-1];
|
||||
}
|
||||
deletearray @i[0],getarraysize(@i);
|
||||
if (.Shops$[.@i] == "") {
|
||||
if (.Shops$[@shop_index] == "") {
|
||||
message strcharinfo(0),"An error has occurred.";
|
||||
end;
|
||||
}
|
||||
dispbottom "Select one item at a time.";
|
||||
callshop "qshop"+.@i,1;
|
||||
npcshopattach "qshop"+.@i;
|
||||
callshop "qshop"+@shop_index,1;
|
||||
npcshopattach "qshop"+@shop_index;
|
||||
end;
|
||||
|
||||
OnBuyItem:
|
||||
// .@q[] : RewardID, BoughtAmt, RewardAmt, BaseAmt, ReqZeny, ReqPts, { ReqItem, ReqAmt, ... }
|
||||
setarray .@q[0],@bought_nameid[0],((@bought_quantity[0] > .MaxStack)?.MaxStack:@bought_quantity[0]);
|
||||
copyarray .@q[3],getd(".q_"+.@q[0]+"[0]"),getarraysize(getd(".q_"+.@q[0]));
|
||||
copyarray .@q[3],getd(".q_"+@shop_index+"_"+.@q[0]+"[0]"),getarraysize(getd(".q_"+@shop_index+"_"+.@q[0]));
|
||||
set .@q[2],.@q[1]*.@q[3];
|
||||
if (!.@q[2] || .@q[2] > 30000) {
|
||||
message strcharinfo(0),"You can't purchase that many "+getitemname(.@q[0])+".";
|
||||
@ -186,7 +186,7 @@ function Add {
|
||||
} else
|
||||
setarray .@j[.@i-2],getarg(.@i),getarg(.@i+1);
|
||||
}
|
||||
copyarray getd(".q_"+getarg(1)+"[0]"),.@j[0],getarraysize(.@j);
|
||||
copyarray getd(".q_"+getarg(0)+"_"+getarg(1)+"[0]"),.@j[0],getarraysize(.@j);
|
||||
npcshopadditem "qshop"+getarg(0),getarg(1),((.ShowZeny)?getarg(3):0);
|
||||
return;
|
||||
}
|
||||
@ -224,4 +224,4 @@ function script qshop {
|
||||
- shop qshop2 -1,909:-1
|
||||
- shop qshop3 -1,909:-1
|
||||
- shop qshop4 -1,909:-1
|
||||
- shop qshop5 -1,909:-1
|
||||
- shop qshop5 -1,909:-1
|
||||
|
@ -1977,7 +1977,7 @@ OnTouch:
|
||||
mapannounce strnpcinfo(4),strcharinfo(0) +" is second to reach the Finish Line! Congratulations!",bc_map,"0xFFFF00";
|
||||
if (.@w$ == "e8" || .@w$ == "n8") setarray .@pts, 28961,40;
|
||||
if (.@w$ == "e16" || .@w$ == "n16") setarray .@pts, 28951,50;
|
||||
if (tt_points < .@pts[0]) set tt_point,tt_point+.@pts[1];
|
||||
if (tt_point < .@pts[0]) set tt_point,tt_point+.@pts[1];
|
||||
warp "turbo_room",72,89;
|
||||
disablenpc "#cos_"+.@w$+"_end2";
|
||||
enablenpc "#cos_"+.@w$+"_end3";
|
||||
|
@ -906,7 +906,7 @@ lhz_cube,237,183,0 script Barrel#cube 111,{
|
||||
mes "you can only enter single";
|
||||
mes "digit numbers at one time...^000000";
|
||||
next;
|
||||
for( set $@i, 0; .@i < 9; set .@i, .@i + 1 )
|
||||
for( set .@i, 0; .@i < 9; set .@i, .@i + 1 )
|
||||
input .@input;
|
||||
mes "^3355FFNothing happened...^000000";
|
||||
close;
|
||||
@ -923,7 +923,7 @@ lhz_cube,237,183,0 script Barrel#cube 111,{
|
||||
mes "metal plate on top of the box";
|
||||
mes "you found inside the keg.^000000";
|
||||
next;
|
||||
for( set $@i, 0; .@i < 9; set .@i, .@i + 1 ) {
|
||||
for( set .@i, 0; .@i < 9; set .@i, .@i + 1 ) {
|
||||
input .@input;
|
||||
if (.@input == .@numbers[.@i]) set .@number_line,.@number_line+1;
|
||||
}
|
||||
|
@ -12611,7 +12611,7 @@ function script F_UpdateSignVars {
|
||||
set sign_fail,0;
|
||||
set gaananpoint,0;
|
||||
set gaanantest,0;
|
||||
set arianstest,0;
|
||||
set ariantest,0;
|
||||
set SignJore,0;
|
||||
set ScareAlchSign,0;
|
||||
set dearles_test,0;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -677,7 +677,7 @@ REPLACE INTO `item_db_re` VALUES (1290,'Agent_Katar','Agent Katar',5,41000,NULL,
|
||||
REPLACE INTO `item_db_re` VALUES (1291,'Guillotine_Katar','Guillotine Katar',5,56000,NULL,1500,'200',NULL,1,1,0x00001000,63,2,34,4,'140',1,16,'bonus bDex,2; bonus bFlee,-30; bonus2 bAddRace,RC_DemiHuman,50; bonus2 bAddRace,RC_Player,50; bonus2 bSkillAtk,"GC_CROSSIMPACT",30;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (1292,'Upg_Katar','Upg Katar',5,20,NULL,1000,'80',NULL,1,1,0x00001000,63,2,34,3,'1',1,16,'bonus bBaseAtk,(getrefine()*10); bonus bCritAtkRate,(getrefine()*2); if(BaseLevel>70) bonus bBaseAtk,(((BaseLevel-70)/10)*10);',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (1293,'Velum_Jamadhar','Vellum Jamadhar',5,20,NULL,1200,'170',NULL,1,0,0x00001000,63,2,34,4,'95',1,16,'bonus4 bSetDefRace,RC_Player,10000,5000,1; bonus4 bSetMDefRace,RC_Player,10000,5000,1; bonus bAspdRate,getrefine();',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (1294,'Velum_Scare','Vellum Scale',5,20,NULL,1200,'50',NULL,1,0,0x00001000,63,2,34,4,'95',1,16,'bonus2 bSPVanishRate,10000,10;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (1294,'Velum_Scare','Vellum Scale',5,20,NULL,1200,'50',NULL,1,0,0x00001000,63,2,34,4,'95',1,16,'bonus3 bSPVanishRaceRate,RC_Player,10000,10;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (1295,'Blood_Tears_','Blood Tears',5,20,NULL,1700,'120',NULL,1,1,0x00001000,18,2,34,4,'55',1,16,NULL,NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (1296,'Metal_Katar','Metal Katar',5,20,NULL,0,'75',NULL,1,1,0x00001000,63,2,34,3,'1',1,16,'bonus bBaseAtk,(getrefine()*5); bonus bCritAtkRate,getrefine(); set .@i,((BaseLevel/10)>12)?12:(BaseLevel/10); if(.@i>2) bonus bBaseAtk,((.@i-2)*5);',NULL,NULL);
|
||||
#
|
||||
@ -747,7 +747,7 @@ REPLACE INTO `item_db_re` VALUES (1391,'P_Two_Handed_Axe1','Eden Two-Handed Axe
|
||||
REPLACE INTO `item_db_re` VALUES (1392,'Ygnus_Stale','Ignus Steel',5,56000,NULL,1900,'250',NULL,1,1,0x000444A2,63,2,34,4,'95',1,7,'bonus bAtkEle,Ele_Fire; bonus bUnbreakableWeapon,0;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (1393,'End_Sektura','End Sectora',5,56000,NULL,1900,'250',NULL,1,1,0x000444A2,63,2,34,4,'95',1,7,'bonus bAtkEle,Ele_Water; bonus bUnbreakableWeapon,0;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (1394,'Upg_Two_Handed_Axe','Upg Two Handed Axe',5,20,NULL,2000,'110',NULL,1,1,0x000444A2,63,2,34,3,'1',1,7,'bonus bBaseAtk,(getrefine()*14); if(BaseLevel>70) bonus bBaseAtk,(((BaseLevel-70)/10)*10);',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (1395,'Velum_Buster','Vellum Buster',5,20,NULL,2500,'50',NULL,1,0,0x000444A2,63,2,34,4,'95',1,7,'bonus bUnbreakableWeapon,0; bonus2 bSPVanishRate,10000,10;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (1395,'Velum_Buster','Vellum Buster',5,20,NULL,2500,'50',NULL,1,0,0x000444A2,63,2,34,4,'95',1,7,'bonus bUnbreakableWeapon,0; bonus3 bSPVanishRaceRate,RC_Player,10000,10;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (1396,'Velum_Guillotine','Vellum Guillotine',5,20,NULL,5500,'300',NULL,1,0,0x000444A2,63,2,34,4,'95',1,7,'bonus bUnbreakableWeapon,0; bonus2 bAddRace,RC_Player,40; bonus2 bIgnoreDefRaceRate,RC_Player,30; if(getrefine()>=6) { bonus2 bSkillAtk,"NC_AXEBOOMERANG",80; bonus2 bSkillAtk,"NC_POWERSWING",80; } if(getrefine()>=9) { bonus2 bAddRace,RC_Player,60; }',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (1397,'Bradium_Stonehammer_','Bradium Stonehammer',5,20,NULL,2700,'210',NULL,1,2,0x000444A2,63,2,34,4,'75',1,7,'bonus bUnbreakableWeapon,0;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (1398,'Metal_Two_Handed_Axe','Metal Two Handed Axe',5,20,NULL,0,'105',NULL,1,1,0x000444A2,63,2,34,3,'1',1,7,'bonus bUnbreakableWeapon,0; bonus bBaseAtk,(getrefine()*7); set .@i,((BaseLevel/10)>12)?12:(BaseLevel/10); if(.@i>2) bonus bBaseAtk,((.@i-2)*5);',NULL,NULL);
|
||||
@ -8974,7 +8974,7 @@ REPLACE INTO `item_db_re` VALUES (18109,'Catapult','Thief Crossbow',5,56000,NULL
|
||||
REPLACE INTO `item_db_re` VALUES (18110,'Big_CrossBow','Giant Crossbow',5,56000,NULL,900,'160',NULL,5,2,0x00000800,63,2,34,4,'110',1,11,'bonus2 bSkillAtk,"RA_ARROWSTORM",(getrefine()*5); bonus2 bSkillUseSP,"RA_ARROWSTORM",(getrefine()*5); if(readparam(bAgi)>=120){ bonus bAspd,1; }',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (18111,'Creeper_Bow','Creeper Bow',5,56000,NULL,1500,'150',NULL,5,2,0x00080800,63,2,34,3,'120',1,11,'bonus bDex,1; bonus3 bAutoSpell,"PF_SPIDERWEB",1,200;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (18112,'Upg_Bow','Upg Bow',5,20,NULL,600,'60',NULL,5,1,0x000A0848,63,2,34,3,'1',0,11,'bonus bBaseAtk,(getrefine()*7); bonus bLongAtkRate,(getrefine()*2); if(BaseJob==Job_Hunter) bonus bBaseAtk,20; if(BaseLevel>70) bonus bBaseAtk,(((BaseLevel-70)/10)*10);',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (18113,'Velum_Arbalest','Vellum Arbalest',5,20,NULL,1100,'50',NULL,5,0,0x000A0848,63,2,34,4,'95',1,11,'bonus2 bSPVanishRate,10000,4; bonus bAspd,-5;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (18113,'Velum_Arbalest','Vellum Arbalest',5,20,NULL,1100,'50',NULL,5,0,0x000A0848,63,2,34,4,'95',1,11,'bonus3 bSPVanishRaceRate,RC_Player,10000,4; bonus bAspd,-5;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (18114,'Velum_CrossBow','Vellum CrossBow',5,20,NULL,1100,'110',NULL,5,0,0x000A0848,63,2,34,4,'95',1,11,'bonus2 bAddRace,RC_Player,30+getrefine(); bonus2 bIgnoreDefRaceRate,RC_Player,30;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (18115,'Orc_Archer_Bow_','Orc Archer Bow',5,20,NULL,1600,'120',NULL,5,1,0x000A0848,63,2,34,3,'65',1,11,NULL,NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (18116,'Metal_Bow','Metal Bow',5,20,NULL,0,'50',NULL,5,1,0x00080800,63,2,34,3,'1',1,11,'if(BaseJob==Job_Hunter && Upper!=2) bonus bBaseAtk,10; bonus bBaseAtk,(getrefine()*3); bonus bLongAtkRate,getrefine(); set .@i,((BaseLevel/10)>12)?12:(BaseLevel/10); if(.@i>2) bonus bBaseAtk,((.@i-2)*5);',NULL,NULL);
|
||||
@ -9722,7 +9722,7 @@ REPLACE INTO `item_db_re` VALUES (20761,'C_Happiness_Wings','Costume Happiness W
|
||||
# More 2-Handed Swords
|
||||
REPLACE INTO `item_db_re` VALUES (21000,'Upg_Twohand_Sword','Upg Two-Handed Sword',5,20,NULL,1500,'100',NULL,1,1,0x00004082,63,2,34,3,'1',1,3,'bonus bBaseAtk,(getrefine()*12); bonus bMatk,(getrefine()*5); if(BaseLevel>70) bonus bBaseAtk,(((BaseLevel-70)/10)*10);',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (21001,'Velum_Claymore','Vellum Claymore',5,20,NULL,3500,'260',NULL,1,0,0x00004082,63,2,34,4,'95',1,3,'bonus2 bAddRace,RC_Player,80; bonus2 bIgnoreDefRaceRate,RC_Player,30; if(getrefine()>=6) { bonus2 bAddRace,RC_Player,40; } if(getrefine()>=9) { autobonus2 "{ bonus bShortWeaponDamageReturn,20; bonus bMagicDamageReturn,20; }",6000,2000,BF_WEAPON,"{ specialeffect2 EF_REFLECTSHIELD; }"; }',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (21002,'Velum_Katzbalger','Vellum Katzbalger',5,20,NULL,2500,'100',NULL,1,0,0x00004082,63,2,34,4,'95',1,3,'bonus2 bHPVanishRate,10000,8;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (21002,'Velum_Katzbalger','Vellum Katzbalger',5,20,NULL,2500,'100',NULL,1,0,0x00004082,63,2,34,4,'95',1,3,'bonus3 bHPVanishRaceRate,RC_Player,10000,8;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (21003,'Muramasa_','Muramasa',5,20,NULL,1000,'155',NULL,1,2,0x00004082,63,2,34,4,'48',1,3,NULL,NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (21004,'Alca_Bringer_','Alca Bringer',5,20,NULL,3400,'280',NULL,2,2,0x00004082,63,2,34,3,'100',1,3,NULL,NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (21005,'Metal_Two_Hand_Sword','Metal Two Hand Sword',5,20,NULL,0,'95',NULL,1,1,0x00004082,63,2,34,3,'1',1,3,'bonus bBaseAtk,(getrefine()*6); bonus bMatk,(getrefine()*2); set .@i,((BaseLevel/10)>12)?12:(BaseLevel/10); if(.@i>2) bonus bBaseAtk,((.@i-2)*5);',NULL,NULL);
|
||||
@ -9909,10 +9909,10 @@ REPLACE INTO `item_db_re` VALUES (22829,'Sealed_Card_Album','Sealed Card Album',
|
||||
REPLACE INTO `item_db_re` VALUES (22837,'Integer_Time','Integer Time',2,10,NULL,100,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'getitem 673,5;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (22838,'Something_Present_Candy_Holders','Something Present Candy Holders',2,10,NULL,100,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (22842,'Sealed_Dracula_Scroll_II','Sealed Dracula Scroll II',2,10,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'getitem callfunc("F_Rand",22846,6228,6232,24223,24227,17474/*, Enchant Letter*/),1;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (22843,'Superstar_Snack','Superstar Snack',2,10,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'bonus_script "{ bonus bAtk2,50; bonus bMatk,50; }",300;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (22843,'Superstar_Snack','Superstar Snack',2,10,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'bonus_script "{ bonus bAtk2,50; bonus bMatk,50; }",300;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (22844,'Sealed_Dracula_Card_Album','Sealed Dracula Card Album',2,10,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'/*No Info*/',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (22845,'Sealed_Fortune_Egg','Sealed Fortune Egg',2,10,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'getitem callfunc("F_Rand",4488,4497,4486,4480,4485,4539,4487,4494,4538,4489,4490,4482,4503,22846),1;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (22846,'Sealed_Dracula_Card','Sealed Dracula Card',2,10,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'bonus_script "{ bonus3 bSPDrainRate,50,5,0; }",300;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (22846,'Sealed_Dracula_Card','Sealed Dracula Card',2,10,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'bonus_script "{ bonus3 bSPDrainRate,50,5,0; }",300;',NULL,NULL);
|
||||
# Shadow Equip
|
||||
REPLACE INTO `item_db_re` VALUES (24000,'T_STR1_Armor_Shadow','T STR1 Armor Shadow',12,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,65536,NULL,'1',NULL,NULL,'bonus bStr,1;',NULL,NULL);
|
||||
REPLACE INTO `item_db_re` VALUES (24001,'T_DEX1_Weapon_Shadow','T DEX1 Weapon Shadow',12,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,131072,NULL,'1',NULL,NULL,'bonus bDex,1;',NULL,NULL);
|
||||
|
@ -706,12 +706,12 @@ CREATE TABLE IF NOT EXISTS `interreg` (
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `bonus_script` (
|
||||
`char_id` varchar(11) NOT NULL,
|
||||
`script` varchar(1024) NOT NULL,
|
||||
`tick` varchar(11) NOT NULL DEFAULT '0',
|
||||
`flag` varchar(3) NOT NULL DEFAULT '0',
|
||||
`type` char(1) NOT NULL DEFAULT '0',
|
||||
`icon` varchar(3) NOT NULL DEFAULT '-1'
|
||||
`char_id` INT(11) UNSIGNED NOT NULL,
|
||||
`script` TEXT NOT NULL,
|
||||
`tick` INT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`flag` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`type` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`icon` SMALLINT(3) NOT NULL DEFAULT '-1'
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `vending_items` (
|
||||
|
6
sql-files/upgrades/upgrade_20150131.sql
Normal file
6
sql-files/upgrades/upgrade_20150131.sql
Normal file
@ -0,0 +1,6 @@
|
||||
ALTER TABLE `bonus_script` MODIFY COLUMN `char_id` INT(11) UNSIGNED NOT NULL;
|
||||
ALTER TABLE `bonus_script` MODIFY COLUMN `script` TEXT NOT NULL;
|
||||
ALTER TABLE `bonus_script` MODIFY COLUMN `tick` INT(11) UNSIGNED NOT NULL DEFAULT '0';
|
||||
ALTER TABLE `bonus_script` MODIFY COLUMN `flag` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0';
|
||||
ALTER TABLE `bonus_script` MODIFY COLUMN `type` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0';
|
||||
ALTER TABLE `bonus_script` MODIFY COLUMN `icon` SMALLINT(3) NOT NULL DEFAULT '-1';
|
@ -1049,15 +1049,15 @@ int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_ev
|
||||
p->save_point.map = mapindex_name2id(save_map);
|
||||
|
||||
if( p->last_point.map == 0 ) {
|
||||
p->last_point.map = mapindex_name2id(MAP_DEFAULT);
|
||||
p->last_point.x = MAP_DEFAULT_X;
|
||||
p->last_point.y = MAP_DEFAULT_Y;
|
||||
p->last_point.map = mapindex_name2id(charserv_config.default_map);
|
||||
p->last_point.x = charserv_config.default_map_x;
|
||||
p->last_point.y = charserv_config.default_map_y;
|
||||
}
|
||||
|
||||
if( p->save_point.map == 0 ) {
|
||||
p->save_point.map = mapindex_name2id(MAP_DEFAULT);
|
||||
p->save_point.x = MAP_DEFAULT_X;
|
||||
p->save_point.y = MAP_DEFAULT_Y;
|
||||
p->save_point.map = mapindex_name2id(charserv_config.default_map);
|
||||
p->save_point.x = charserv_config.default_map_x;
|
||||
p->save_point.y = charserv_config.default_map_y;
|
||||
}
|
||||
|
||||
StringBuf_Init(&msg_buf);
|
||||
@ -2536,6 +2536,10 @@ void char_set_defaults(){
|
||||
charserv_config.autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
|
||||
charserv_config.start_zeny = 0;
|
||||
charserv_config.guild_exp_rate = 100;
|
||||
|
||||
safestrncpy(charserv_config.default_map, "prontera", MAP_NAME_LENGTH);
|
||||
charserv_config.default_map_x = 156;
|
||||
charserv_config.default_map_y = 191;
|
||||
}
|
||||
|
||||
bool char_config_read(const char* cfgName, bool normal){
|
||||
@ -2725,6 +2729,12 @@ bool char_config_read(const char* cfgName, bool normal){
|
||||
charserv_config.charmove_config.char_moves_unlimited = config_switch(w2);
|
||||
} else if (strcmpi(w1, "char_checkdb") == 0) {
|
||||
charserv_config.char_check_db = config_switch(w2);
|
||||
} else if (strcmpi(w1, "default_map") == 0) {
|
||||
safestrncpy(charserv_config.default_map, w2, MAP_NAME_LENGTH);
|
||||
} else if (strcmpi(w1, "default_map_x") == 0) {
|
||||
charserv_config.default_map_x = atoi(w2);
|
||||
} else if (strcmpi(w1, "default_map_y") == 0) {
|
||||
charserv_config.default_map_y = atoi(w2);
|
||||
} else if (strcmpi(w1, "import") == 0) {
|
||||
char_config_read(w2, normal);
|
||||
}
|
||||
@ -2912,6 +2922,8 @@ int do_init(int argc, char **argv)
|
||||
}
|
||||
|
||||
do_init_chcnslif();
|
||||
mapindex_check_mapdefault(charserv_config.default_map);
|
||||
ShowInfo("Default map: '"CL_WHITE"%s %d,%d"CL_RESET"'\n", charserv_config.default_map, charserv_config.default_map_x, charserv_config.default_map_y);
|
||||
|
||||
ShowStatus("The char-server is "CL_GREEN"ready"CL_RESET" (Server is listening on the port %d).\n\n", charserv_config.char_port);
|
||||
|
||||
|
@ -135,6 +135,10 @@ struct CharServ_Config {
|
||||
int autosave_interval;
|
||||
int start_zeny;
|
||||
int guild_exp_rate;
|
||||
|
||||
char default_map[MAP_NAME_LENGTH];
|
||||
unsigned short default_map_x;
|
||||
unsigned short default_map_y;
|
||||
};
|
||||
extern struct CharServ_Config charserv_config;
|
||||
|
||||
|
@ -160,6 +160,79 @@ void chmapif_sendall_playercount(int users){
|
||||
chmapif_sendall(buf,6);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send some misc info to new map-server.
|
||||
* - Server name for whisper name
|
||||
* - Default map
|
||||
* HZ 0x2afb <size>.W <status>.B <name>.24B <mapname>.11B <map_x>.W <map_y>.W
|
||||
* @param fd
|
||||
**/
|
||||
static void chmapif_send_misc(int fd) {
|
||||
uint16 offs = 5;
|
||||
unsigned char buf[45];
|
||||
|
||||
memset(buf, '\0', sizeof(buf));
|
||||
WBUFW(buf, 0) = 0x2afb;
|
||||
// 0 succes, 1:failure
|
||||
WBUFB(buf, 4) = 0;
|
||||
// Send name for wisp to player
|
||||
memcpy(WBUFP(buf, 5), charserv_config.wisp_server_name, NAME_LENGTH);
|
||||
// Default map
|
||||
memcpy(WBUFP(buf, (offs+=NAME_LENGTH)), charserv_config.default_map, MAP_NAME_LENGTH); // 29
|
||||
WBUFW(buf, (offs+=MAP_NAME_LENGTH)) = charserv_config.default_map_x; // 41
|
||||
WBUFW(buf, (offs+=2)) = charserv_config.default_map_y; // 43
|
||||
offs+=2;
|
||||
|
||||
// Length
|
||||
WBUFW(buf, 2) = offs;
|
||||
chmapif_send(fd, buf, offs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends maps to all map-server
|
||||
* HZ 0x2b04 <size>.W <ip>.L <port>.W { <map>.?B }.?B
|
||||
* @param fd
|
||||
* @param map_id
|
||||
* @param count Number of map from new map-server has
|
||||
**/
|
||||
static void chmapif_send_maps(int fd, int map_id, int count, unsigned char *mapbuf) {
|
||||
uint16 x;
|
||||
|
||||
if (count == 0) {
|
||||
ShowWarning("Map-server %d has NO maps.\n", map_id);
|
||||
}
|
||||
else {
|
||||
unsigned char buf[16384];
|
||||
// Transmitting maps information to the other map-servers
|
||||
WBUFW(buf,0) = 0x2b04;
|
||||
WBUFW(buf,2) = count * 4 + 10;
|
||||
WBUFL(buf,4) = htonl(map_server[map_id].ip);
|
||||
WBUFW(buf,8) = htons(map_server[map_id].port);
|
||||
memcpy(WBUFP(buf,10), mapbuf, count * 4);
|
||||
chmapif_sendallwos(fd, buf, WBUFW(buf,2));
|
||||
}
|
||||
|
||||
// Transmitting the maps of the other map-servers to the new map-server
|
||||
for (x = 0; x < ARRAYLENGTH(map_server); x++) {
|
||||
if (map_server[x].fd > 0 && x != map_id) {
|
||||
uint16 i, j;
|
||||
|
||||
WFIFOHEAD(fd,10 +4*ARRAYLENGTH(map_server[x].map));
|
||||
WFIFOW(fd,0) = 0x2b04;
|
||||
WFIFOL(fd,4) = htonl(map_server[x].ip);
|
||||
WFIFOW(fd,8) = htons(map_server[x].port);
|
||||
j = 0;
|
||||
for(i = 0; i < ARRAYLENGTH(map_server[x].map); i++)
|
||||
if (map_server[x].map[i])
|
||||
WFIFOW(fd,10+(j++)*4) = map_server[x].map[i];
|
||||
if (j > 0) {
|
||||
WFIFOW(fd,2) = j * 4 + 10;
|
||||
WFIFOSET(fd,WFIFOW(fd,2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called when the map-serv initialise is chrif interface.
|
||||
* Map-serv sent us his map indexes so we can transfert a player from a map-serv to another when necessary
|
||||
@ -169,7 +242,9 @@ void chmapif_sendall_playercount(int users){
|
||||
* @return : 0 not enough data received, 1 success
|
||||
*/
|
||||
int chmapif_parse_getmapname(int fd, int id){
|
||||
int j = 0, i = 0;
|
||||
int i = 0, j = 0;
|
||||
unsigned char *mapbuf;
|
||||
|
||||
if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
|
||||
return 0;
|
||||
|
||||
@ -180,52 +255,17 @@ int chmapif_parse_getmapname(int fd, int id){
|
||||
j++;
|
||||
}
|
||||
|
||||
mapbuf = RFIFOP(fd,4);
|
||||
RFIFOSKIP(fd,RFIFOW(fd,2));
|
||||
|
||||
ShowStatus("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d.\n",
|
||||
id, j, CONVIP(map_server[id].ip), map_server[id].port);
|
||||
ShowStatus("Map-server %d loading complete.\n", id);
|
||||
|
||||
// send name for wisp to player
|
||||
WFIFOHEAD(fd, 3 + NAME_LENGTH);
|
||||
WFIFOW(fd,0) = 0x2afb;
|
||||
WFIFOB(fd,2) = 0; //0 succes, 1:failure
|
||||
memcpy(WFIFOP(fd,3), charserv_config.wisp_server_name, NAME_LENGTH);
|
||||
WFIFOSET(fd,3+NAME_LENGTH);
|
||||
|
||||
chmapif_send_misc(fd);
|
||||
chmapif_send_fame_list(fd); //Send fame list.
|
||||
chmapif_send_maps(fd, id, j, mapbuf);
|
||||
|
||||
{
|
||||
int x;
|
||||
if (j == 0) {
|
||||
ShowWarning("Map-server %d has NO maps.\n", id);
|
||||
} else {
|
||||
unsigned char buf[16384];
|
||||
// Transmitting maps information to the other map-servers
|
||||
WBUFW(buf,0) = 0x2b04;
|
||||
WBUFW(buf,2) = j * 4 + 10;
|
||||
WBUFL(buf,4) = htonl(map_server[id].ip);
|
||||
WBUFW(buf,8) = htons(map_server[id].port);
|
||||
memcpy(WBUFP(buf,10), RFIFOP(fd,4), j * 4);
|
||||
chmapif_sendallwos(fd, buf, WBUFW(buf,2));
|
||||
}
|
||||
// Transmitting the maps of the other map-servers to the new map-server
|
||||
for(x = 0; x < ARRAYLENGTH(map_server); x++) {
|
||||
if (map_server[x].fd > 0 && x != id) {
|
||||
WFIFOHEAD(fd,10 +4*ARRAYLENGTH(map_server[x].map));
|
||||
WFIFOW(fd,0) = 0x2b04;
|
||||
WFIFOL(fd,4) = htonl(map_server[x].ip);
|
||||
WFIFOW(fd,8) = htons(map_server[x].port);
|
||||
j = 0;
|
||||
for(i = 0; i < ARRAYLENGTH(map_server[x].map); i++)
|
||||
if (map_server[x].map[i])
|
||||
WFIFOW(fd,10+(j++)*4) = map_server[x].map[i];
|
||||
if (j > 0) {
|
||||
WFIFOW(fd,2) = j * 4 + 10;
|
||||
WFIFOSET(fd,WFIFOW(fd,2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
RFIFOSKIP(fd,RFIFOW(fd,2));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1242,91 +1282,116 @@ int chmapif_parse_reqcharunban(int fd){
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** [Cydh]
|
||||
* Get bonus_script data(s) from table to load
|
||||
* @param fd
|
||||
*/
|
||||
/**
|
||||
* ZA 0x2b2d
|
||||
* <cmd>.W <char_id>.L
|
||||
* AZ 0x2b2f
|
||||
* <cmd>.W <len>.W <cid>.L <count>.B { <bonus_script_data>.?B }
|
||||
* Get bonus_script data(s) from table to load then send to player
|
||||
* @param fd
|
||||
* @author [Cydh]
|
||||
**/
|
||||
int chmapif_bonus_script_get(int fd) {
|
||||
if (RFIFOREST(fd) < 6)
|
||||
return 0;
|
||||
else {
|
||||
int cid;
|
||||
cid = RFIFOL(fd,2);
|
||||
uint8 num_rows = 0;
|
||||
uint32 cid = RFIFOL(fd,2);
|
||||
struct bonus_script_data tmp_bsdata;
|
||||
SqlStmt* stmt = SqlStmt_Malloc(sql_handle);
|
||||
|
||||
RFIFOSKIP(fd,6);
|
||||
|
||||
if (SQL_ERROR == Sql_Query(sql_handle,"SELECT `script`, `tick`, `flag`, `type`, `icon` FROM `%s` WHERE `char_id`='%d'",
|
||||
schema_config.bonus_script_db,cid))
|
||||
if (SQL_ERROR == SqlStmt_Prepare(stmt,
|
||||
"SELECT `script`, `tick`, `flag`, `type`, `icon` FROM `%s` WHERE `char_id` = '%d' LIMIT %d",
|
||||
schema_config.bonus_script_db, cid, MAX_PC_BONUS_SCRIPT) ||
|
||||
SQL_ERROR == SqlStmt_Execute(stmt) ||
|
||||
SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_STRING, &tmp_bsdata.script_str, sizeof(tmp_bsdata.script_str), NULL, NULL) ||
|
||||
SQL_ERROR == SqlStmt_BindColumn(stmt, 1, SQLDT_UINT32, &tmp_bsdata.tick, 0, NULL, NULL) ||
|
||||
SQL_ERROR == SqlStmt_BindColumn(stmt, 2, SQLDT_UINT16, &tmp_bsdata.flag, 0, NULL, NULL) ||
|
||||
SQL_ERROR == SqlStmt_BindColumn(stmt, 3, SQLDT_UINT8, &tmp_bsdata.type, 0, NULL, NULL) ||
|
||||
SQL_ERROR == SqlStmt_BindColumn(stmt, 4, SQLDT_INT16, &tmp_bsdata.icon, 0, NULL, NULL)
|
||||
)
|
||||
{
|
||||
Sql_ShowDebug(sql_handle);
|
||||
SqlStmt_ShowDebug(stmt);
|
||||
SqlStmt_Free(stmt);
|
||||
return 1;
|
||||
}
|
||||
if (Sql_NumRows(sql_handle) > 0) {
|
||||
struct bonus_script_data bsdata;
|
||||
int count;
|
||||
char *data;
|
||||
|
||||
WFIFOHEAD(fd,10+50*sizeof(struct bonus_script_data));
|
||||
WFIFOW(fd,0) = 0x2b2f;
|
||||
WFIFOL(fd,4) = cid;
|
||||
for (count = 0; count < MAX_PC_BONUS_SCRIPT && SQL_SUCCESS == Sql_NextRow(sql_handle); ++count) {
|
||||
Sql_GetData(sql_handle,0,&data,NULL); memcpy(bsdata.script,data,strlen(data)+1);
|
||||
Sql_GetData(sql_handle,1,&data,NULL); bsdata.tick = atoi(data);
|
||||
Sql_GetData(sql_handle,2,&data,NULL); bsdata.flag = atoi(data);
|
||||
Sql_GetData(sql_handle,3,&data,NULL); bsdata.type = atoi(data);
|
||||
Sql_GetData(sql_handle,4,&data,NULL); bsdata.icon = atoi(data);
|
||||
memcpy(WFIFOP(fd,10+count*sizeof(struct bonus_script_data)),&bsdata,sizeof(struct bonus_script_data));
|
||||
}
|
||||
if (count >= MAX_PC_BONUS_SCRIPT)
|
||||
ShowWarning("Too many bonus_script for %d, some of them were not loaded.\n",cid);
|
||||
if (count > 0) {
|
||||
WFIFOW(fd,2) = 10 + count*sizeof(struct bonus_script_data);
|
||||
WFIFOW(fd,8) = count;
|
||||
WFIFOSET(fd,WFIFOW(fd,2));
|
||||
if ((num_rows = (uint8)SqlStmt_NumRows(stmt)) > 0) {
|
||||
uint8 i;
|
||||
uint32 size = 9 + num_rows * sizeof(struct bonus_script_data);
|
||||
|
||||
//Clear the data once loaded.
|
||||
if (SQL_ERROR == Sql_Query(sql_handle,"DELETE FROM `%s` WHERE `char_id`='%d'",schema_config.bonus_script_db,cid))
|
||||
Sql_ShowDebug(sql_handle);
|
||||
ShowInfo("Loaded %d bonus_script for char_id: %d\n",count,cid);
|
||||
WFIFOHEAD(fd, size);
|
||||
WFIFOW(fd, 0) = 0x2b2f;
|
||||
WFIFOW(fd, 2) = size;
|
||||
WFIFOL(fd, 4) = cid;
|
||||
WFIFOB(fd, 8) = num_rows;
|
||||
|
||||
for (i = 0; i < num_rows && SQL_SUCCESS == SqlStmt_NextRow(stmt); i++) {
|
||||
struct bonus_script_data bsdata;
|
||||
memset(&bsdata, 0, sizeof(bsdata));
|
||||
memset(bsdata.script_str, '\0', sizeof(bsdata.script_str));
|
||||
|
||||
safestrncpy(bsdata.script_str, tmp_bsdata.script_str, strlen(tmp_bsdata.script_str)+1);
|
||||
bsdata.tick = tmp_bsdata.tick;
|
||||
bsdata.flag = tmp_bsdata.flag;
|
||||
bsdata.type = tmp_bsdata.type;
|
||||
bsdata.icon = tmp_bsdata.icon;
|
||||
memcpy(WFIFOP(fd, 9 + i * sizeof(struct bonus_script_data)), &bsdata, sizeof(struct bonus_script_data));
|
||||
}
|
||||
|
||||
WFIFOSET(fd, size);
|
||||
|
||||
ShowInfo("Bonus Script loaded for CID=%d. Total: %d.\n", cid, i);
|
||||
|
||||
if (SQL_ERROR == SqlStmt_Prepare(stmt,"DELETE FROM `%s` WHERE `char_id`='%d'",schema_config.bonus_script_db,cid) ||
|
||||
SQL_ERROR == SqlStmt_Execute(stmt))
|
||||
SqlStmt_ShowDebug(stmt);
|
||||
}
|
||||
Sql_FreeResult(sql_handle);
|
||||
SqlStmt_Free(stmt);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** [Cydh]
|
||||
* Save bonus_script data(s) to the table
|
||||
* @param fd
|
||||
*/
|
||||
/**
|
||||
* ZA 0x2b2e
|
||||
* <cmd>.W <len>.W <char_id>.L <count>.B { <bonus_script>.?B }
|
||||
* Save bonus_script data(s) to the table
|
||||
* @param fd
|
||||
* @author [Cydh]
|
||||
**/
|
||||
int chmapif_bonus_script_save(int fd) {
|
||||
if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
|
||||
return 0;
|
||||
else {
|
||||
int count, cid;
|
||||
uint32 cid = RFIFOL(fd,4);
|
||||
uint8 count = RFIFOB(fd,8);
|
||||
|
||||
cid = RFIFOL(fd,4);
|
||||
count = RFIFOW(fd,8);
|
||||
if (SQL_ERROR == Sql_Query(sql_handle,"DELETE FROM `%s` WHERE `char_id` = '%d'", schema_config.bonus_script_db, cid))
|
||||
Sql_ShowDebug(sql_handle);
|
||||
|
||||
if (count > 0) {
|
||||
struct bonus_script_data bs;
|
||||
char esc_script[MAX_BONUS_SCRIPT_LENGTH*2];
|
||||
struct bonus_script_data bsdata;
|
||||
StringBuf buf;
|
||||
int i;
|
||||
char esc_script[MAX_BONUS_SCRIPT_LENGTH] = "";
|
||||
uint8 i;
|
||||
|
||||
StringBuf_Init(&buf);
|
||||
StringBuf_Printf(&buf,"INSERT INTO `%s` (`char_id`, `script`, `tick`, `flag`, `type`, `icon`) VALUES ",schema_config.bonus_script_db);
|
||||
StringBuf_Printf(&buf, "INSERT INTO `%s` (`char_id`, `script`, `tick`, `flag`, `type`, `icon`) VALUES ", schema_config.bonus_script_db);
|
||||
for (i = 0; i < count; ++i) {
|
||||
memcpy(&bs,RFIFOP(fd,10+i*sizeof(struct bonus_script_data)),sizeof(struct bonus_script_data));
|
||||
Sql_EscapeString(sql_handle,esc_script,bs.script);
|
||||
memcpy(&bsdata, RFIFOP(fd, 9 + i*sizeof(struct bonus_script_data)), sizeof(struct bonus_script_data));
|
||||
Sql_EscapeString(sql_handle, esc_script, bsdata.script_str);
|
||||
if (i > 0)
|
||||
StringBuf_AppendStr(&buf,", ");
|
||||
StringBuf_Printf(&buf,"('%d','%s','%d','%d','%d','%d')",cid,esc_script,bs.tick,bs.flag,bs.type,bs.icon);
|
||||
StringBuf_Printf(&buf, "('%d','%s','%d','%d','%d','%d')", cid, esc_script, bsdata.tick, bsdata.flag, bsdata.type, bsdata.icon);
|
||||
}
|
||||
if (SQL_ERROR == Sql_QueryStr(sql_handle,StringBuf_Value(&buf)))
|
||||
Sql_ShowDebug(sql_handle);
|
||||
|
||||
StringBuf_Destroy(&buf);
|
||||
ShowInfo("Saved %d bonus_script for char_id: %d\n",count,cid);
|
||||
}
|
||||
ShowInfo("Bonus Script saved for CID=%d. Total: %d.\n", cid, count);
|
||||
RFIFOSKIP(fd,RFIFOW(fd,2));
|
||||
}
|
||||
return 1;
|
||||
|
@ -2717,18 +2717,29 @@ void linkdb_insert( struct linkdb_node** head, void *key, void* data)
|
||||
node->data = data;
|
||||
}
|
||||
|
||||
void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... )
|
||||
{
|
||||
int linkdb_vforeach( struct linkdb_node** head, LinkDBFunc func, va_list ap) {
|
||||
struct linkdb_node *node;
|
||||
if( head == NULL ) return;
|
||||
int retCount = 0;
|
||||
if( head == NULL )
|
||||
return 0;
|
||||
node = *head;
|
||||
while ( node ) {
|
||||
va_list args;
|
||||
va_start(args, func);
|
||||
func( node->key, node->data, args );
|
||||
va_end(args);
|
||||
va_list argscopy;
|
||||
va_copy(argscopy, ap);
|
||||
retCount += func(node->key, node->data, argscopy);
|
||||
va_end(argscopy);
|
||||
node = node->next;
|
||||
}
|
||||
return retCount;
|
||||
}
|
||||
|
||||
int linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... ) {
|
||||
va_list ap;
|
||||
int retCount = 0;
|
||||
va_start(ap, func);
|
||||
retCount = linkdb_vforeach(head, func, ap);
|
||||
va_end(ap);
|
||||
return retCount;
|
||||
}
|
||||
|
||||
void* linkdb_search( struct linkdb_node** head, void *key)
|
||||
|
@ -875,14 +875,15 @@ struct linkdb_node {
|
||||
void *data;
|
||||
};
|
||||
|
||||
typedef void (*LinkDBFunc)(void* key, void* data, va_list args);
|
||||
typedef int (*LinkDBFunc)(void* key, void* data, va_list args);
|
||||
|
||||
void linkdb_insert ( struct linkdb_node** head, void *key, void* data); // 重複を考慮しない
|
||||
void linkdb_replace( struct linkdb_node** head, void *key, void* data); // 重複を考慮する
|
||||
void* linkdb_search ( struct linkdb_node** head, void *key);
|
||||
void* linkdb_erase ( struct linkdb_node** head, void *key);
|
||||
void linkdb_final ( struct linkdb_node** head );
|
||||
void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
|
||||
int linkdb_vforeach(struct linkdb_node** head, LinkDBFunc func, va_list ap);
|
||||
int linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
|
||||
|
||||
|
||||
|
||||
|
@ -107,7 +107,7 @@ int mapindex_addmap(int index, const char* name) {
|
||||
return index;
|
||||
}
|
||||
|
||||
unsigned short mapindex_name2id(const char* name) {
|
||||
unsigned short mapindex_name2idx(const char* name, const char *func) {
|
||||
int i;
|
||||
char map_name[MAP_NAME_LENGTH];
|
||||
mapindex_getmapname(name, map_name);
|
||||
@ -115,14 +115,13 @@ unsigned short mapindex_name2id(const char* name) {
|
||||
if( (i = strdb_iget(mapindex_db, map_name)) )
|
||||
return i;
|
||||
|
||||
ShowDebug("mapindex_name2id: Map \"%s\" not found in index list!\n", map_name);
|
||||
ShowDebug("(%s) mapindex_name2id: Map \"%s\" not found in index list!\n", func, map_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* mapindex_id2name(unsigned short id)
|
||||
{
|
||||
const char* mapindex_idx2name(unsigned short id, const char *func) {
|
||||
if (id > MAX_MAPINDEX || !mapindex_exists(id)) {
|
||||
ShowDebug("mapindex_id2name: Requested name for non-existant map index [%d] in cache.\n", id);
|
||||
ShowDebug("(%s) mapindex_id2name: Requested name for non-existant map index [%d] in cache.\n", func, id);
|
||||
return indexes[0].name; // dummy empty string so that the callee doesn't crash
|
||||
}
|
||||
return indexes[id].name;
|
||||
@ -175,9 +174,16 @@ void mapindex_init(void) {
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
if( !strdb_iget(mapindex_db, MAP_DEFAULT) ) {
|
||||
ShowError("mapindex_init: MAP_DEFAULT '%s' not found in cache! Update MAP_DEFAULT in mapindex.h!\n",MAP_DEFAULT);
|
||||
/**
|
||||
* Check default map (only triggered once by char-server)
|
||||
* @param mapname
|
||||
**/
|
||||
void mapindex_check_mapdefault(const char *mapname) {
|
||||
mapname = mapindex_getmapname(mapname, NULL);
|
||||
if( !strdb_iget(mapindex_db, mapname) ) {
|
||||
ShowError("mapindex_init: Default map '%s' not found in cache! Please change in (by default in) char_athena.conf!\n", mapname);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,19 +45,21 @@
|
||||
#define MAP_ECLAGE "eclage"
|
||||
#define MAP_ECLAGE_IN "ecl_in01"
|
||||
|
||||
// When a map index search fails, return results from what map?
|
||||
#define MAP_DEFAULT MAP_PRONTERA
|
||||
#define MAP_DEFAULT_X 150
|
||||
#define MAP_DEFAULT_Y 150
|
||||
|
||||
const char* mapindex_getmapname(const char* string, char* output);
|
||||
const char* mapindex_getmapname_ext(const char* string, char* output);
|
||||
unsigned short mapindex_name2id(const char*);
|
||||
const char* mapindex_id2name(unsigned short);
|
||||
void mapindex_init(void);
|
||||
void mapindex_final(void);
|
||||
|
||||
unsigned short mapindex_name2idx(const char* name, const char *func);
|
||||
#define mapindex_name2id(mapname) mapindex_name2idx((mapname), __FUNCTION__)
|
||||
|
||||
const char* mapindex_idx2name(unsigned short id, const char *func);
|
||||
#define mapindex_id2name(mapindex) mapindex_idx2name((mapindex), __FUNCTION__)
|
||||
|
||||
int mapindex_addmap(int index, const char* name);
|
||||
int mapindex_removemap(int index);
|
||||
|
||||
void mapindex_check_mapdefault(const char *mapname);
|
||||
|
||||
void mapindex_init(void);
|
||||
void mapindex_final(void);
|
||||
|
||||
#endif /* _MAPINDEX_H_ */
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "cbasetypes.h"
|
||||
#include "../common/db.h"
|
||||
#include <time.h>
|
||||
#include "../common/strlib.h"// StringBuf
|
||||
|
||||
// server->client protocol version
|
||||
// 0 - pre-?
|
||||
@ -73,7 +74,7 @@
|
||||
#define MAX_GUILDLEVEL 50 ///Max Guild level
|
||||
#define MAX_GUARDIANS 8 ///Local max per castle. If this value is increased, need to add more fields on MySQL `guild_castle` table [Skotlex]
|
||||
#define MAX_QUEST_OBJECTIVES 3 ///Max quest objectives for a quest
|
||||
#define MAX_PC_BONUS_SCRIPT 20 ///Max bonus script
|
||||
#define MAX_PC_BONUS_SCRIPT 50 ///Max bonus script can be fetched from `bonus_script` table on player load [Cydh]
|
||||
|
||||
// for produce
|
||||
#define MIN_ATTRIBUTE 0
|
||||
@ -260,12 +261,13 @@ struct status_change_data {
|
||||
long val1, val2, val3, val4, tick; //Remaining duration.
|
||||
};
|
||||
|
||||
#define MAX_BONUS_SCRIPT_LENGTH 1024
|
||||
#define MAX_BONUS_SCRIPT_LENGTH 512
|
||||
struct bonus_script_data {
|
||||
char script[MAX_BONUS_SCRIPT_LENGTH];
|
||||
long tick;
|
||||
char type;
|
||||
short flag, icon;
|
||||
char script_str[MAX_BONUS_SCRIPT_LENGTH]; //< Script string
|
||||
uint32 tick; ///< Tick
|
||||
uint16 flag; ///< Flags @see enum e_bonus_script_flags
|
||||
int16 icon; ///< Icon SI
|
||||
uint8 type; ///< 0 - None, 1 - Buff, 2 - Debuff
|
||||
};
|
||||
|
||||
struct skill_cooldown_data {
|
||||
|
@ -16,13 +16,13 @@ void findfile(const char *p, const char *pat, void (func)(const char*));
|
||||
bool exists(const char* filename);
|
||||
|
||||
/// Caps values to min/max
|
||||
#define cap_value(a, min, max) ((a >= max) ? max : (a <= min) ? min : a)
|
||||
#define cap_value(a, min, max) (((a) >= (max)) ? (max) : ((a) <= (min)) ? (min) : (a))
|
||||
|
||||
/// Apply rate for val, divided by 100)
|
||||
#define apply_rate(val, rate) (((rate) == 100) ? (val) : ((val) > 100000) ? (val) / 100 * (rate) : (val) * (rate) / 100)
|
||||
#define apply_rate(val, rate) (((rate) == 100) ? (val) : ((val) > 100000) ? ((val) / 100 * (rate)) : ((val) * (rate) / 100))
|
||||
|
||||
/// Apply rate for val, divided by per
|
||||
#define apply_rate2(val, rate, per) (((rate) == (per)) ? (val) : ((val) > 100000) ? (val) / (per) * (rate) : (val) * (rate) / (per))
|
||||
#define apply_rate2(val, rate, per) (((rate) == (per)) ? (val) : ((val) > 100000) ? ((val) / (per) * (rate)) : ((val) * (rate) / (per)))
|
||||
|
||||
/// calculates the value of A / B, in percent (rounded down)
|
||||
unsigned int get_percentage(const unsigned int A, const unsigned int B);
|
||||
|
@ -6517,10 +6517,28 @@ void battle_drain(TBL_PC *sd, struct block_list *tbl, int64 rdamage, int64 ldama
|
||||
{
|
||||
struct weapon_data *wd;
|
||||
int64 *damage;
|
||||
int thp = 0, tsp = 0, rhp = 0, rsp = 0, hp=0, sp=0, i;
|
||||
int thp = 0, tsp = 0, rhp = 0, rsp = 0, hp = 0, sp = 0;
|
||||
uint8 i = 0;
|
||||
short vrate_hp = 0, vrate_sp = 0, v_hp = 0, v_sp = 0;
|
||||
|
||||
if (!CHK_RACE(race) && !CHK_CLASS(class_))
|
||||
return;
|
||||
|
||||
// Check for vanish HP/SP. !CHECKME: Which first, drain or vanish?
|
||||
vrate_hp = cap_value(sd->bonus.hp_vanish_rate + sd->vanish_race[race].hp_rate + sd->vanish_race[RC_ALL].hp_rate, SHRT_MIN, SHRT_MAX);
|
||||
v_hp = cap_value(sd->bonus.hp_vanish_per + sd->vanish_race[race].hp_per + sd->vanish_race[RC_ALL].hp_per, INT8_MIN, INT8_MAX);
|
||||
|
||||
vrate_sp = cap_value(sd->bonus.sp_vanish_rate + sd->vanish_race[race].sp_rate + sd->vanish_race[RC_ALL].sp_rate, SHRT_MIN, SHRT_MAX);
|
||||
v_sp = cap_value(sd->bonus.sp_vanish_per + sd->vanish_race[race].sp_per + sd->vanish_race[RC_ALL].sp_per, INT8_MIN, INT8_MAX);
|
||||
|
||||
if (v_hp > 0 && vrate_hp > 0 && (vrate_hp >= 10000 || rnd()%10000 < vrate_hp))
|
||||
i |= 1;
|
||||
if (v_sp > 0 && vrate_sp > 0 && (vrate_sp >= 10000 || rnd()%10000 < vrate_sp))
|
||||
i |= 2;
|
||||
if (i)
|
||||
status_percent_damage(&sd->bl, tbl, (i&1 ? (int8)v_hp: 0), (i&2 ? (int8)v_sp : 0), false);
|
||||
|
||||
i = 0;
|
||||
for (i = 0; i < 4; i++) {
|
||||
//First two iterations: Right hand
|
||||
if (i < 2) { wd = &sd->right_weapon; damage = &rdamage; }
|
||||
@ -6585,13 +6603,6 @@ void battle_drain(TBL_PC *sd, struct block_list *tbl, int64 rdamage, int64 ldama
|
||||
}
|
||||
}
|
||||
|
||||
if (sd->bonus.sp_vanish_rate && rnd()%1000 < sd->bonus.sp_vanish_rate)
|
||||
status_percent_damage(&sd->bl, tbl, 0, (unsigned char)sd->bonus.sp_vanish_per, false);
|
||||
|
||||
if (sd->bonus.hp_vanish_rate && rnd()%1000 < sd->bonus.hp_vanish_rate
|
||||
&& tbl->type == BL_PC && (map[sd->bl.m].flag.pvp || map[sd->bl.m].flag.gvg))
|
||||
status_percent_damage(&sd->bl, tbl, (unsigned char)sd->bonus.hp_vanish_per, 0, false);
|
||||
|
||||
if( sd->sp_gain_race_attack[race] )
|
||||
tsp += sd->sp_gain_race_attack[race];
|
||||
if( sd->sp_gain_race_attack[RC_ALL] )
|
||||
@ -6601,7 +6612,8 @@ void battle_drain(TBL_PC *sd, struct block_list *tbl, int64 rdamage, int64 ldama
|
||||
if( sd->hp_gain_race_attack[RC_ALL] )
|
||||
thp += sd->hp_gain_race_attack[RC_ALL];
|
||||
|
||||
if (!thp && !tsp) return;
|
||||
if (!thp && !tsp)
|
||||
return;
|
||||
|
||||
status_heal(&sd->bl, thp, tsp, battle_config.show_hp_sp_drain?3:1);
|
||||
|
||||
@ -7949,6 +7961,8 @@ static const struct _battle_data {
|
||||
{ "default_fixed_castrate", &battle_config.default_fixed_castrate, 20, 0, 100, },
|
||||
{ "default_bind_on_equip", &battle_config.default_bind_on_equip, BOUND_CHAR, BOUND_NONE, BOUND_MAX-1, },
|
||||
{ "pet_ignore_infinite_def", &battle_config.pet_ignore_infinite_def, 0, 0, 1, },
|
||||
{ "homunculus_evo_intimacy_need", &battle_config.homunculus_evo_intimacy_need, 91100, 0, INT_MAX, },
|
||||
{ "homunculus_evo_intimacy_reset", &battle_config.homunculus_evo_intimacy_reset, 1000, 0, INT_MAX, },
|
||||
};
|
||||
|
||||
#ifndef STATS_OPT_OUT
|
||||
|
@ -585,6 +585,8 @@ extern struct Battle_Config
|
||||
int default_fixed_castrate;
|
||||
int default_bind_on_equip;
|
||||
int pet_ignore_infinite_def; // Makes fixed damage of petskillattack2 ignores infinite defense
|
||||
int homunculus_evo_intimacy_need;
|
||||
int homunculus_evo_intimacy_reset;
|
||||
} battle_config;
|
||||
|
||||
void do_init_battle(void);
|
||||
|
282
src/map/chrif.c
282
src/map/chrif.c
@ -33,7 +33,7 @@ static struct eri *auth_db_ers; //For reutilizing player login structures.
|
||||
static DBMap* auth_db; // int id -> struct auth_node*
|
||||
|
||||
static const int packet_len_table[0x3d] = { // U - used, F - free
|
||||
60, 3,-1,27,10,-1, 6,-1, // 2af8-2aff: U->2af8, U->2af9, U->2afa, U->2afb, U->2afc, U->2afd, U->2afe, U->2aff
|
||||
60, 3,-1,-1,10,-1, 6,-1, // 2af8-2aff: U->2af8, U->2af9, U->2afa, U->2afb, U->2afc, U->2afd, U->2afe, U->2aff
|
||||
6,-1,19, 7,-1,39,30, 10, // 2b00-2b07: U->2b00, U->2b01, U->2b02, U->2b03, U->2b04, U->2b05, U->2b06, U->2b07
|
||||
6,30, 10, -1,86, 7,44,34, // 2b08-2b0f: U->2b08, U->2b09, U->2b0a, U->2b0b, U->2b0c, U->2b0d, U->2b0e, U->2b0f
|
||||
11,10,10, 0,11, -1,266,10, // 2b10-2b17: U->2b10, U->2b11, U->2b12, F->2b13, U->2b14, U->2b15, U->2b16, U->2b17
|
||||
@ -46,7 +46,7 @@ static const int packet_len_table[0x3d] = { // U - used, F - free
|
||||
//2af8: Outgoing, chrif_connect -> 'connect to charserver / auth @ charserver'
|
||||
//2af9: Incoming, chrif_connectack -> 'answer of the 2af8 login(ok / fail)'
|
||||
//2afa: Outgoing, chrif_sendmap -> 'sending our maps'
|
||||
//2afb: Incoming, chrif_sendmapack -> 'Maps received successfully / or not ..'
|
||||
//2afb: Incoming, chrif_sendmapack -> 'Maps received successfully / or not .. also received server name & default map'
|
||||
//2afc: Outgoing, chrif_scdata_request -> request sc_data for pc_authok'ed char. <- new command reuses previous one.
|
||||
//2afd: Incoming, chrif_authok -> 'client authentication ok'
|
||||
//2afe: Outgoing, send_usercount_tochar -> 'sends player count of this map server to charserver'
|
||||
@ -97,8 +97,8 @@ static const int packet_len_table[0x3d] = { // U - used, F - free
|
||||
//2b2b: Incoming, chrif_parse_ack_vipActive -> vip info result
|
||||
//2b2c: FREE
|
||||
//2b2d: Outgoing, chrif_bsdata_request -> request bonus_script for pc_authok'ed char.
|
||||
//2b2e: Outgoing, chrif_save_bsdata -> Send bonus_script of player for saving.
|
||||
//2b2f: Incoming, chrif_load_bsdata -> received bonus_script of player for loading.
|
||||
//2b2e: Outgoing, chrif_bsdata_save -> Send bonus_script of player for saving.
|
||||
//2b2f: Incoming, chrif_bsdata_received -> received bonus_script of player for loading.
|
||||
|
||||
int chrif_connected = 0;
|
||||
int char_fd = -1;
|
||||
@ -282,7 +282,6 @@ int chrif_save(struct map_session_data *sd, int flag) {
|
||||
if (chrif_isconnected()) {
|
||||
chrif_save_scdata(sd);
|
||||
chrif_skillcooldown_save(sd);
|
||||
chrif_save_bsdata(sd);
|
||||
chrif_req_login_operation(sd->status.account_id, sd->status.name, CHRIF_OP_LOGIN_BANK, 0, 2, sd->status.bank_vault); //save Bank data
|
||||
}
|
||||
if ( flag != 3 && !chrif_auth_logout(sd,flag == 1 ? ST_LOGOUT : ST_MAPCHANGE) )
|
||||
@ -291,6 +290,8 @@ int chrif_save(struct map_session_data *sd, int flag) {
|
||||
|
||||
chrif_check(-1); //Character is saved on reconnect.
|
||||
|
||||
chrif_bsdata_save(sd, (flag && (flag != 3)));
|
||||
|
||||
//For data sync
|
||||
if (sd->state.storage_flag == 2)
|
||||
gstorage_storagesave(sd->status.account_id, sd->status.guild_id, flag);
|
||||
@ -562,17 +563,30 @@ void chrif_on_ready(void) {
|
||||
}
|
||||
|
||||
|
||||
/*==========================================
|
||||
*
|
||||
*------------------------------------------*/
|
||||
/**
|
||||
* Maps are sent, then received misc info from char-server
|
||||
* - Server name
|
||||
* - Default map
|
||||
* HZ 0x2afb
|
||||
**/
|
||||
int chrif_sendmapack(int fd) {
|
||||
uint16 offs = 5;
|
||||
|
||||
if (RFIFOB(fd,2)) {
|
||||
if (RFIFOB(fd,4)) {
|
||||
ShowFatalError("chrif : send map list to char server failed %d\n", RFIFOB(fd,2));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
memcpy(wisp_server_name, RFIFOP(fd,3), NAME_LENGTH);
|
||||
// Server name
|
||||
memcpy(wisp_server_name, RFIFOP(fd,5), NAME_LENGTH);
|
||||
ShowStatus("Map-server connected to char-server '"CL_WHITE"%s"CL_RESET"'.\n", wisp_server_name);
|
||||
|
||||
// Default map
|
||||
memcpy(map_default.mapname, RFIFOP(fd, (offs+=NAME_LENGTH)), MAP_NAME_LENGTH);
|
||||
map_default.x = RFIFOW(fd, (offs+=MAP_NAME_LENGTH));
|
||||
map_default.y = RFIFOW(fd, (offs+=2));
|
||||
if (battle_config.etc_log)
|
||||
ShowInfo("Received default map from char-server '"CL_WHITE"%s %d,%d"CL_RESET"'.\n", map_default.mapname, map_default.x, map_default.y);
|
||||
|
||||
chrif_on_ready();
|
||||
|
||||
@ -1600,6 +1614,130 @@ void chrif_parse_ack_vipActive(int fd) {
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ZA 0x2b2d
|
||||
* <cmd>.W <char_id>.L
|
||||
* Requets bonus_script datas
|
||||
* @param char_id
|
||||
* @author [Cydh]
|
||||
**/
|
||||
int chrif_bsdata_request(uint32 char_id) {
|
||||
chrif_check(-1);
|
||||
WFIFOHEAD(char_fd,6);
|
||||
WFIFOW(char_fd,0) = 0x2b2d;
|
||||
WFIFOL(char_fd,2) = char_id;
|
||||
WFIFOSET(char_fd,6);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ZA 0x2b2e
|
||||
* <cmd>.W <len>.W <char_id>.L <count>.B { <bonus_script>.?B }
|
||||
* Stores bonus_script data(s) to the table
|
||||
* @param sd
|
||||
* @author [Cydh]
|
||||
**/
|
||||
int chrif_bsdata_save(struct map_session_data *sd, bool quit) {
|
||||
uint8 i = 0;
|
||||
|
||||
chrif_check(-1);
|
||||
|
||||
if (!sd)
|
||||
return 0;
|
||||
|
||||
// Removing...
|
||||
if (quit && sd->bonus_script.head) {
|
||||
uint16 flag = BSF_REM_ON_LOGOUT; //Remove bonus when logout
|
||||
if (battle_config.debuff_on_logout&1) //Remove negative buffs
|
||||
flag |= BSF_REM_DEBUFF;
|
||||
if (battle_config.debuff_on_logout&2) //Remove positive buffs
|
||||
flag |= BSF_REM_BUFF;
|
||||
pc_bonus_script_clear(sd, flag);
|
||||
}
|
||||
|
||||
//ShowInfo("Saving %d bonus script for CID=%d\n", sd->bonus_script.count, sd->status.char_id);
|
||||
|
||||
WFIFOHEAD(char_fd, 9 + sd->bonus_script.count * sizeof(struct bonus_script_data));
|
||||
WFIFOW(char_fd, 0) = 0x2b2e;
|
||||
WFIFOL(char_fd, 4) = sd->status.char_id;
|
||||
|
||||
if (sd->bonus_script.count) {
|
||||
unsigned int tick = gettick();
|
||||
struct linkdb_node *node = NULL;
|
||||
|
||||
for (node = sd->bonus_script.head; node && i < MAX_PC_BONUS_SCRIPT; node = node->next) {
|
||||
const struct TimerData *timer = NULL;
|
||||
struct bonus_script_data bs;
|
||||
struct s_bonus_script_entry *entry = (struct s_bonus_script_entry *)node->data;
|
||||
|
||||
if (!entry || !(timer = get_timer(entry->tid)) || DIFF_TICK(timer->tick,tick) < 0)
|
||||
continue;
|
||||
|
||||
memset(&bs, 0, sizeof(bs));
|
||||
safestrncpy(bs.script_str, StringBuf_Value(entry->script_buf), StringBuf_Length(entry->script_buf)+1);
|
||||
bs.tick = DIFF_TICK(timer->tick, tick);
|
||||
bs.flag = entry->flag;
|
||||
bs.type = entry->type;
|
||||
bs.icon = entry->icon;
|
||||
memcpy(WFIFOP(char_fd, 9 + i * sizeof(struct bonus_script_data)), &bs, sizeof(struct bonus_script_data));
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i != sd->bonus_script.count && sd->bonus_script.count > MAX_PC_BONUS_SCRIPT)
|
||||
ShowWarning("Only allowed to save %d (mmo.h::MAX_PC_BONUS_SCRIPT) bonus script each player.\n", MAX_PC_BONUS_SCRIPT);
|
||||
}
|
||||
|
||||
WFIFOB(char_fd, 8) = i;
|
||||
WFIFOW(char_fd, 2) = 9 + sd->bonus_script.count * sizeof(struct bonus_script_data);
|
||||
WFIFOSET(char_fd, WFIFOW(char_fd, 2));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* AZ 0x2b2f
|
||||
* <cmd>.W <len>.W <cid>.L <count>.B { <bonus_script_data>.?B }
|
||||
* Bonus script received, set to player
|
||||
* @param fd
|
||||
* @author [Cydh]
|
||||
**/
|
||||
int chrif_bsdata_received(int fd) {
|
||||
struct map_session_data *sd;
|
||||
uint32 cid = RFIFOL(fd,4);
|
||||
uint8 count = 0;
|
||||
|
||||
sd = map_charid2sd(cid);
|
||||
|
||||
if (!sd) {
|
||||
ShowError("chrif_bsdata_received: Player with CID %d not found!\n",cid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((count = RFIFOB(fd,8))) {
|
||||
uint8 i = 0;
|
||||
|
||||
//ShowInfo("Loaded %d bonus script for CID=%d\n", count, sd->status.char_id);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
struct bonus_script_data *bs = (struct bonus_script_data*)RFIFOP(fd,9 + i*sizeof(struct bonus_script_data));
|
||||
struct s_bonus_script_entry *entry = NULL;
|
||||
|
||||
if (bs->script_str[0] == '\0' || !bs->tick)
|
||||
continue;
|
||||
|
||||
if (!(entry = pc_bonus_script_add(sd, bs->script_str, bs->tick, (enum si_type)bs->icon, bs->flag, bs->type)))
|
||||
continue;
|
||||
|
||||
linkdb_insert(&sd->bonus_script.head, (void *)((intptr_t)entry), entry);
|
||||
}
|
||||
|
||||
if (sd->bonus_script.head)
|
||||
status_calc_pc(sd,SCO_NONE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
*
|
||||
*------------------------------------------*/
|
||||
@ -1678,7 +1816,7 @@ int chrif_parse(int fd) {
|
||||
case 0x2b27: chrif_authfail(fd); break;
|
||||
case 0x2b29: chrif_load_bankdata(fd); break;
|
||||
case 0x2b2b: chrif_parse_ack_vipActive(fd); break;
|
||||
case 0x2b2f: chrif_load_bsdata(fd); break;
|
||||
case 0x2b2f: chrif_bsdata_received(fd); break;
|
||||
default:
|
||||
ShowError("chrif_parse : unknown packet (session #%d): 0x%x. Disconnecting.\n", fd, cmd);
|
||||
set_eof(fd);
|
||||
@ -1800,121 +1938,6 @@ int chrif_send_report(char* buf, int len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** [Cydh]
|
||||
* Requets bonus_script datas
|
||||
* @param char_id
|
||||
*/
|
||||
int chrif_bsdata_request(uint32 char_id) {
|
||||
chrif_check(-1);
|
||||
WFIFOHEAD(char_fd,6);
|
||||
WFIFOW(char_fd,0) = 0x2b2d;
|
||||
WFIFOL(char_fd,2) = char_id;
|
||||
WFIFOSET(char_fd,6);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** [Cydh]
|
||||
* Stores bonus_script data(s) to the table
|
||||
* @param sd
|
||||
*/
|
||||
int chrif_save_bsdata(struct map_session_data *sd) {
|
||||
int i;
|
||||
uint8 count = 0;
|
||||
unsigned int tick;
|
||||
struct bonus_script_data bs;
|
||||
const struct TimerData *timer;
|
||||
|
||||
chrif_check(-1);
|
||||
tick = gettick();
|
||||
|
||||
WFIFOHEAD(char_fd,10+MAX_PC_BONUS_SCRIPT*sizeof(struct bonus_script_data));
|
||||
WFIFOW(char_fd,0) = 0x2b2e;
|
||||
WFIFOL(char_fd,4) = sd->status.char_id;
|
||||
|
||||
i = BSF_REM_ON_LOGOUT; //Remove bonus with this flag
|
||||
if (battle_config.debuff_on_logout&1) //Remove negative buffs
|
||||
i |= BSF_REM_DEBUFF;
|
||||
if (battle_config.debuff_on_logout&2) //Remove positive buffs
|
||||
i |= BSF_REM_BUFF;
|
||||
|
||||
//Clear data that won't be stored
|
||||
pc_bonus_script_clear(sd,i);
|
||||
|
||||
for (i = 0; i < MAX_PC_BONUS_SCRIPT; i++) {
|
||||
if (!(&sd->bonus_script[i]) || !sd->bonus_script[i].script || sd->bonus_script[i].script_str[0] == '\0')
|
||||
continue;
|
||||
|
||||
timer = get_timer(sd->bonus_script[i].tid);
|
||||
if (timer == NULL || DIFF_TICK(timer->tick,tick) < 0)
|
||||
continue;
|
||||
|
||||
memcpy(bs.script,sd->bonus_script[i].script_str,strlen(sd->bonus_script[i].script_str)+1);
|
||||
bs.tick = DIFF_TICK(timer->tick,tick);
|
||||
bs.flag = sd->bonus_script[i].flag;
|
||||
bs.type = sd->bonus_script[i].type;
|
||||
bs.icon = sd->bonus_script[i].icon;
|
||||
|
||||
memcpy(WFIFOP(char_fd,10+count*sizeof(struct bonus_script_data)),&bs,sizeof(struct bonus_script_data));
|
||||
pc_bonus_script_remove(&sd->bonus_script[i]);
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0)
|
||||
return 0;
|
||||
|
||||
WFIFOW(char_fd,8) = count;
|
||||
WFIFOW(char_fd,2) = 10+count*sizeof(struct bonus_script_data);
|
||||
WFIFOSET(char_fd,WFIFOW(char_fd,2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** [Cydh]
|
||||
* Loads bonus_script datas
|
||||
* @param fd
|
||||
*/
|
||||
int chrif_load_bsdata(int fd) {
|
||||
struct map_session_data *sd;
|
||||
int cid, count;
|
||||
uint8 i;
|
||||
bool calc = false;
|
||||
|
||||
cid = RFIFOL(fd,4);
|
||||
sd = map_charid2sd(cid);
|
||||
|
||||
if (!sd) {
|
||||
ShowError("chrif_load_bsdata: Player with CID %d not found!\n",cid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sd->status.char_id != cid) {
|
||||
ShowError("chrif_load_bsdata: Receiving data for char id does not matches (%d != %d)!\n",sd->status.char_id,cid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
count = RFIFOW(fd,8);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
struct script_code *script;
|
||||
struct bonus_script_data *bs = (struct bonus_script_data*)RFIFOP(fd,10 + i*sizeof(struct bonus_script_data));
|
||||
|
||||
if (bs->script[0] == '\0' || !(script = parse_script(bs->script,"chrif_load_bsdata",1,1)))
|
||||
continue;
|
||||
|
||||
memcpy(sd->bonus_script[i].script_str,bs->script,strlen(bs->script));
|
||||
sd->bonus_script[i].script = script;
|
||||
sd->bonus_script[i].tick = gettick() + bs->tick;
|
||||
sd->bonus_script[i].flag = (uint8)bs->flag;
|
||||
sd->bonus_script[i].type = bs->type;
|
||||
sd->bonus_script[i].icon = bs->icon;
|
||||
if (bs->icon != SI_BLANK) //Gives status icon if exist
|
||||
clif_status_change(&sd->bl,sd->bonus_script[i].icon,1,bs->tick,1,0,0);
|
||||
calc = true;
|
||||
}
|
||||
if (calc)
|
||||
status_calc_pc(sd,SCO_NONE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DBApply
|
||||
*/
|
||||
@ -1956,6 +1979,13 @@ void do_init_chrif(void) {
|
||||
sizeof(struct mmo_charstatus));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if((sizeof(struct bonus_script_data) * MAX_PC_BONUS_SCRIPT) > 0xFFFF){
|
||||
ShowError("bonus_script_data size = %d is too big, please reduce MAX_PC_BONUS_SCRIPT (%d) size. (must be below 0xFFFF).\n",
|
||||
(sizeof(struct bonus_script_data) * MAX_PC_BONUS_SCRIPT), MAX_PC_BONUS_SCRIPT);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
auth_db = idb_alloc(DB_OPT_BASE);
|
||||
auth_db_ers = ers_new(sizeof(struct auth_node),"chrif.c::auth_db_ers",ERS_OPT_NONE);
|
||||
|
||||
|
@ -89,8 +89,7 @@ int chrif_req_charunban(int aid, const char* character_name);
|
||||
int chrif_load_bankdata(int fd);
|
||||
|
||||
int chrif_bsdata_request(uint32 char_id);
|
||||
int chrif_save_bsdata(struct map_session_data *sd);
|
||||
int chrif_load_bsdata(int fd);
|
||||
int chrif_bsdata_save(struct map_session_data *sd, bool quit);
|
||||
|
||||
void do_final_chrif(void);
|
||||
void do_init_chrif(void);
|
||||
|
@ -1517,7 +1517,7 @@ int clif_homskillinfoblock(struct map_session_data *sd)
|
||||
WFIFOW(fd,len+8) = skill_get_sp(id,hd->homunculus.hskill[idx].lv);
|
||||
WFIFOW(fd,len+10)= skill_get_range2(&sd->hd->bl, id,hd->homunculus.hskill[idx].lv);
|
||||
safestrncpy((char*)WFIFOP(fd,len+12), skill_get_name(id), NAME_LENGTH);
|
||||
WFIFOB(fd,len+36) = (hd->homunculus.hskill[idx].lv < hom_skill_tree_get_max(id, hd->homunculus.class_))?1:0;
|
||||
WFIFOB(fd,len+36) = (hd->homunculus.level < hom_skill_get_min_level(hd->homunculus.class_, id) || hd->homunculus.hskill[idx].lv >= hom_skill_tree_get_max(id, hd->homunculus.class_)) ? 0 : 1;
|
||||
len+=37;
|
||||
}
|
||||
}
|
||||
@ -1546,7 +1546,7 @@ void clif_homskillup(struct map_session_data *sd, uint16 skill_id)
|
||||
WFIFOW(fd,4) = hd->homunculus.hskill[idx].lv;
|
||||
WFIFOW(fd,6) = skill_get_sp(skill_id,hd->homunculus.hskill[idx].lv);
|
||||
WFIFOW(fd,8) = skill_get_range2(&hd->bl, skill_id,hd->homunculus.hskill[idx].lv);
|
||||
WFIFOB(fd,10) = (hd->homunculus.hskill[idx].lv < skill_get_max(hd->homunculus.hskill[idx].id)) ? 1 : 0;
|
||||
WFIFOB(fd,10) = (hd->homunculus.level < hom_skill_get_min_level(hd->homunculus.class_, skill_id) || hd->homunculus.hskill[idx].lv >= hom_skill_tree_get_max(hd->homunculus.hskill[idx].id, hd->homunculus.class_)) ? 0 : 1;
|
||||
WFIFOSET(fd,packet_len(0x239));
|
||||
}
|
||||
|
||||
|
@ -1960,11 +1960,12 @@ int guild_castledatasave(int castle_id, int index, int value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void guild_castle_reconnect_sub(void *key, void *data, va_list ap) {
|
||||
int guild_castle_reconnect_sub(void *key, void *data, va_list ap) {
|
||||
int castle_id = GetWord((int)__64BPRTSIZE(key), 0);
|
||||
int index = GetWord((int)__64BPRTSIZE(key), 1);
|
||||
intif_guild_castle_datasave(castle_id, index, *(int *)data);
|
||||
aFree(data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
struct s_homunculus_db homunculus_db[MAX_HOMUNCULUS_CLASS]; //[orn]
|
||||
struct homun_skill_tree_entry hskill_tree[MAX_HOMUNCULUS_CLASS][MAX_SKILL_TREE];
|
||||
struct homun_skill_tree_entry hskill_tree[MAX_HOMUNCULUS_CLASS][MAX_HOM_SKILL_TREE];
|
||||
|
||||
static int hom_hungry(int tid, unsigned int tick, int id, intptr_t data);
|
||||
static uint16 homunculus_count;
|
||||
@ -33,10 +33,26 @@ static unsigned int hexptbl[MAX_LEVEL];
|
||||
//For holding the view data of npc classes. [Skotlex]
|
||||
static struct view_data hom_viewdb[MAX_HOMUNCULUS_CLASS];
|
||||
|
||||
struct s_homun_intimacy_grade {
|
||||
//const char *grade;
|
||||
uint32 min_value;
|
||||
};
|
||||
|
||||
/// Intimacy grade, order based on enum e_homun_grade
|
||||
static struct s_homun_intimacy_grade intimacy_grades[] = {
|
||||
{ /*"Hate with passion",*/ 100 },
|
||||
{ /*"Hate", */ 400 },
|
||||
{ /*"Awkward", */ 1100 },
|
||||
{ /*"Shy", */ 10100 },
|
||||
{ /*"Neutral", */ 25100 },
|
||||
{ /*"Cordial", */ 75100 },
|
||||
{ /*"Loyal", */ 91100 },
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the skill is a valid homunculus skill based skill range or availablity in skill db
|
||||
* @param skill_id
|
||||
* @return -1 if invalid skill or skill index for homunculus skill_tree
|
||||
* @return -1 if invalid skill or skill index for homunculus skill in s_homunculus::hskill
|
||||
*/
|
||||
short hom_skill_get_index(uint16 skill_id) {
|
||||
if (!SKILL_CHK_HOMUN(skill_id))
|
||||
@ -258,8 +274,7 @@ int hom_delete(struct homun_data *hd, int emote)
|
||||
* @param hd
|
||||
* @param flag_envolve
|
||||
*/
|
||||
void hom_calc_skilltree(struct homun_data *hd, int flag_evolve)
|
||||
{
|
||||
void hom_calc_skilltree(struct homun_data *hd, bool flag_evolve) {
|
||||
uint8 i;
|
||||
short c = 0;
|
||||
|
||||
@ -277,6 +292,8 @@ void hom_calc_skilltree(struct homun_data *hd, int flag_evolve)
|
||||
continue; //Skill already known.
|
||||
if (!battle_config.skillfree) {
|
||||
uint8 j;
|
||||
if (hskill_tree[c][i].need_level > hd->homunculus.level)
|
||||
continue;
|
||||
for (j = 0; j < MAX_HOM_SKILL_REQUIRE; j++) {
|
||||
if (hskill_tree[c][i].need[j].id &&
|
||||
hom_checkskill(hd,hskill_tree[c][i].need[j].id) < hskill_tree[c][i].need[j].lv)
|
||||
@ -296,7 +313,7 @@ void hom_calc_skilltree(struct homun_data *hd, int flag_evolve)
|
||||
return;
|
||||
|
||||
for (i = 0; i < MAX_SKILL_TREE; i++) {
|
||||
unsigned int intimacy;
|
||||
unsigned int intimacy = 0;
|
||||
uint16 skill_id;
|
||||
short idx = -1;
|
||||
bool fail = false;
|
||||
@ -305,10 +322,12 @@ void hom_calc_skilltree(struct homun_data *hd, int flag_evolve)
|
||||
if (hd->homunculus.hskill[idx].id)
|
||||
continue; //Skill already known.
|
||||
intimacy = (flag_evolve) ? 10 : hd->homunculus.intimacy;
|
||||
if (intimacy < hskill_tree[c][i].intimacylv)
|
||||
if (intimacy < hskill_tree[c][i].intimacy * 100)
|
||||
continue;
|
||||
if (!battle_config.skillfree) {
|
||||
int j;
|
||||
uint8 j;
|
||||
if (hskill_tree[c][i].need_level > hd->homunculus.level)
|
||||
continue;
|
||||
for (j = 0; j < MAX_HOM_SKILL_REQUIRE; j++) {
|
||||
if (hskill_tree[c][i].need[j].id &&
|
||||
hom_checkskill(hd,hskill_tree[c][i].need[j].id) < hskill_tree[c][i].need[j].lv)
|
||||
@ -354,18 +373,35 @@ short hom_checkskill(struct homun_data *hd,uint16 skill_id)
|
||||
* @return Skill Level
|
||||
*/
|
||||
int hom_skill_tree_get_max(int skill_id, int b_class){
|
||||
int i, skid;
|
||||
uint8 i;
|
||||
|
||||
if ((b_class = hom_class2index(b_class)) < 0)
|
||||
return 0;
|
||||
for (i = 0; (skid = hskill_tree[b_class][i].id) > 0; i++) {
|
||||
if (hom_skill_get_index(skid) < 0)
|
||||
return 0;
|
||||
if (skill_id == skid)
|
||||
return hskill_tree[b_class][i].max;
|
||||
}
|
||||
ARR_FIND(0, MAX_HOM_SKILL_TREE, i, hskill_tree[b_class][i].id == skill_id);
|
||||
if (i < MAX_HOM_SKILL_TREE)
|
||||
return hskill_tree[b_class][i].max;
|
||||
return skill_get_max(skill_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get required minimum level to learn the skill
|
||||
* @param class_ Homunculus class
|
||||
* @param skill_id Homunculus skill ID
|
||||
* @return Level required or 0 if invalid
|
||||
**/
|
||||
uint8 hom_skill_get_min_level(int class_, uint16 skill_id) {
|
||||
short class_idx = hom_class2index(class_), skill_idx = -1;
|
||||
uint8 i;
|
||||
|
||||
if (class_idx == -1 || (skill_idx = hom_skill_get_index(skill_id)) == -1)
|
||||
return 0;
|
||||
ARR_FIND(0, MAX_HOM_SKILL_REQUIRE, i, hskill_tree[class_idx][i].id == skill_id);
|
||||
if (i == MAX_HOM_SKILL_REQUIRE)
|
||||
return 0;
|
||||
|
||||
return hskill_tree[class_idx][i].need_level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Level up an homunculus skill
|
||||
* @param hd
|
||||
@ -384,6 +420,7 @@ void hom_skillup(struct homun_data *hd, uint16 skill_id)
|
||||
if (hd->homunculus.skillpts > 0 &&
|
||||
hd->homunculus.hskill[idx].id &&
|
||||
hd->homunculus.hskill[idx].flag == SKILL_FLAG_PERMANENT && //Don't allow raising while you have granted skills. [Skotlex]
|
||||
hd->homunculus.level >= hom_skill_get_min_level(hd->homunculus.class_, skill_id) &&
|
||||
hd->homunculus.hskill[idx].lv < hom_skill_tree_get_max(skill_id, hd->homunculus.class_)
|
||||
)
|
||||
{
|
||||
@ -543,7 +580,7 @@ int hom_evolution(struct homun_data *hd)
|
||||
hom->int_+= 10*rnd_value(min->int_,max->int_);
|
||||
hom->dex += 10*rnd_value(min->dex, max->dex);
|
||||
hom->luk += 10*rnd_value(min->luk, max->luk);
|
||||
hom->intimacy = 500;
|
||||
hom->intimacy = battle_config.homunculus_evo_intimacy_reset;
|
||||
|
||||
unit_remove_map(&hd->bl, CLR_OUTSIGHT);
|
||||
if (map_addblock(&hd->bl))
|
||||
@ -1294,28 +1331,40 @@ int hom_shuffle(struct homun_data *hd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get minimum intimacy value of specified grade
|
||||
* @param grade see enum e_homun_grade
|
||||
* @return Intimacy value
|
||||
**/
|
||||
uint32 hom_intimacy_grade2intimacy(enum e_homun_grade grade) {
|
||||
if (grade < HOMGRADE_HATE_WITH_PASSION || grade > HOMGRADE_LOYAL)
|
||||
return 0;
|
||||
return intimacy_grades[grade].min_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get grade of given intimacy value
|
||||
* @param intimacy
|
||||
* @return Grade, see enum e_homun_grade
|
||||
**/
|
||||
enum e_homun_grade hom_intimacy_intimacy2grade(uint32 intimacy) {
|
||||
#define CHK_HOMINTIMACY(grade) { if (intimacy >= intimacy_grades[(grade)].min_value) return (grade); }
|
||||
CHK_HOMINTIMACY(HOMGRADE_LOYAL)
|
||||
CHK_HOMINTIMACY(HOMGRADE_CORDIAL)
|
||||
CHK_HOMINTIMACY(HOMGRADE_NEUTRAL)
|
||||
CHK_HOMINTIMACY(HOMGRADE_SHY)
|
||||
CHK_HOMINTIMACY(HOMGRADE_AWKWARD)
|
||||
CHK_HOMINTIMACY(HOMGRADE_HATE)
|
||||
#undef CHK_HOMINTIMACY
|
||||
return HOMGRADE_HATE_WITH_PASSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get initmacy grade
|
||||
* @param hd
|
||||
*/
|
||||
uint8 hom_get_intimacy_grade(struct homun_data *hd)
|
||||
{
|
||||
unsigned int val = hd->homunculus.intimacy / 100;
|
||||
|
||||
if( val > 100 ) {
|
||||
if( val > 250 ) {
|
||||
if( val > 750 ) {
|
||||
if ( val > 900 )
|
||||
return 4;
|
||||
else
|
||||
return 3;
|
||||
} else
|
||||
return 2;
|
||||
} else
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
uint8 hom_get_intimacy_grade(struct homun_data *hd) {
|
||||
return hom_intimacy_intimacy2grade(hd->homunculus.intimacy);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1462,16 +1511,12 @@ void read_homunculusdb(void) {
|
||||
|
||||
/**
|
||||
* Read homunculus skill db
|
||||
* <hom class>,<skill id>,<max level>,<need level>,<req id1>,<req lv1>,<req id2>,<req lv2>,<req id3>,<req lv3>,<req id4>,<req lv4>,<req id5>,<req lv5>,<intimacy lv req>
|
||||
*/
|
||||
static bool read_homunculus_skilldb_sub(char* split[], int columns, int current)
|
||||
{// <hom class>,<skill id>,<max level>[,<job level>],<req id1>,<req lv1>,<req id2>,<req lv2>,<req id3>,<req lv3>,<req id4>,<req lv4>,<req id5>,<req lv5>,<intimacy lv req>
|
||||
static bool read_homunculus_skilldb_sub(char* split[], int columns, int current) {
|
||||
uint16 skill_id;
|
||||
uint8 i;
|
||||
int8 i;
|
||||
short class_idx, idx = -1;
|
||||
int minJobLevelPresent = 0;
|
||||
|
||||
if (columns == 15)
|
||||
minJobLevelPresent = 1; // MinJobLvl has been added
|
||||
|
||||
// check for bounds [celest]
|
||||
if ((class_idx = hom_class2index(atoi(split[0]))) == -1) {
|
||||
@ -1487,30 +1532,27 @@ static bool read_homunculus_skilldb_sub(char* split[], int columns, int current)
|
||||
|
||||
hskill_tree[class_idx][idx].id = skill_id;
|
||||
hskill_tree[class_idx][idx].max = atoi(split[2]);
|
||||
if (minJobLevelPresent)
|
||||
hskill_tree[class_idx][idx].joblv = atoi(split[3]);
|
||||
hskill_tree[class_idx][idx].need_level = atoi(split[3]);
|
||||
|
||||
for (i = 0; i < MAX_HOM_SKILL_REQUIRE; i++) {
|
||||
hskill_tree[class_idx][idx].need[i].id = atoi(split[3+i*2+minJobLevelPresent]);
|
||||
hskill_tree[class_idx][idx].need[i].lv = atoi(split[3+i*2+minJobLevelPresent+1]);
|
||||
hskill_tree[class_idx][idx].need[i].id = atoi(split[4+i*2]);
|
||||
hskill_tree[class_idx][idx].need[i].lv = atoi(split[4+i*2+1]);
|
||||
}
|
||||
|
||||
hskill_tree[class_idx][idx].intimacylv = atoi(split[13+minJobLevelPresent]);
|
||||
hskill_tree[class_idx][idx].intimacy = atoi(split[14]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read homunculus skill db (check the files)
|
||||
*/
|
||||
int read_homunculus_skilldb(void)
|
||||
{
|
||||
const char *filename[]={ "homun_skill_tree.txt",DBIMPORT"/homun_skill_tree.txt"};
|
||||
static void read_homunculus_skilldb(void) {
|
||||
const char *filename[] = { "homun_skill_tree.txt", DBIMPORT"/homun_skill_tree.txt"};
|
||||
int i;
|
||||
memset(hskill_tree,0,sizeof(hskill_tree));
|
||||
for(i = 0; i<ARRAYLENGTH(filename); i++){
|
||||
sv_readdb(db_path, filename[i], ',', 14, 15, -1, &read_homunculus_skilldb_sub, i);
|
||||
for (i = 0; i<ARRAYLENGTH(filename); i++) {
|
||||
sv_readdb(db_path, filename[i], ',', 15, 15, -1, &read_homunculus_skilldb_sub, i);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -68,16 +68,19 @@ struct homun_data {
|
||||
};
|
||||
|
||||
#define MAX_HOM_SKILL_REQUIRE 5
|
||||
#define MAX_HOM_SKILL_TREE 8
|
||||
|
||||
/// Homunculus skill entry [Celest]
|
||||
struct homun_skill_tree_entry {
|
||||
short id;
|
||||
unsigned char max;
|
||||
unsigned char joblv;
|
||||
short intimacylv;
|
||||
uint16 id; ///< Skill ID
|
||||
uint8 max; ///< Max level for this tree
|
||||
uint8 need_level; ///< Homunculus level required
|
||||
uint16 intimacy; ///< Intimacy required (n/100)
|
||||
struct {
|
||||
short id;
|
||||
unsigned char lv;
|
||||
} need[MAX_HOM_SKILL_REQUIRE];
|
||||
}; // Celest
|
||||
uint16 id; ///< Skill ID
|
||||
uint8 lv; ///< Level of skill
|
||||
} need[MAX_HOM_SKILL_REQUIRE]; ///< Skills needed
|
||||
};
|
||||
|
||||
#define HOM_EVO 0x100 //256
|
||||
#define HOM_S 0x200 //512
|
||||
@ -123,6 +126,16 @@ enum homun_setting {
|
||||
HOMSET_RESET_REUSESKILL_TELEPORTED = 0x80, /// Skill re-use delay is reset when they are warped (by skill or item) with player.
|
||||
};
|
||||
|
||||
enum e_homun_grade {
|
||||
HOMGRADE_HATE_WITH_PASSION = 0,
|
||||
HOMGRADE_HATE,
|
||||
HOMGRADE_AWKWARD,
|
||||
HOMGRADE_SHY,
|
||||
HOMGRADE_NEUTRAL,
|
||||
HOMGRADE_CORDIAL,
|
||||
HOMGRADE_LOYAL,
|
||||
};
|
||||
|
||||
/// Check Homunculus Class ID
|
||||
#define homdb_checkid(id) (id >= HM_CLASS_BASE && id <= HM_CLASS_MAX)
|
||||
|
||||
@ -135,8 +148,9 @@ enum homun_type hom_class2type(int class_);
|
||||
void hom_damage(struct homun_data *hd);
|
||||
int hom_dead(struct homun_data *hd);
|
||||
void hom_skillup(struct homun_data *hd,uint16 skill_id);
|
||||
void hom_calc_skilltree(struct homun_data *hd, int flag_evolve);
|
||||
void hom_calc_skilltree(struct homun_data *hd, bool flag_evolve);
|
||||
short hom_checkskill(struct homun_data *hd,uint16 skill_id);
|
||||
uint8 hom_skill_get_min_level(int class_, uint16 skill_id);
|
||||
void hom_gainexp(struct homun_data *hd,int exp);
|
||||
int hom_levelup(struct homun_data *hd);
|
||||
int hom_evolution(struct homun_data *hd);
|
||||
@ -169,6 +183,8 @@ void hom_addspiritball(TBL_HOM *hd, int max);
|
||||
void hom_delspiritball(TBL_HOM *hd, int count, int type);
|
||||
|
||||
uint8 hom_get_intimacy_grade(struct homun_data *hd);
|
||||
uint32 hom_intimacy_grade2intimacy(enum e_homun_grade grade);
|
||||
enum e_homun_grade hom_intimacy_intimacy2grade(uint32 intimacy);
|
||||
|
||||
short hom_skill_get_index(uint16 skill_id);
|
||||
|
||||
|
@ -147,6 +147,8 @@ char charhelp_txt[256] = "conf/charhelp.txt";
|
||||
|
||||
char wisp_server_name[NAME_LENGTH] = "Server"; // can be modified in char-server configuration file
|
||||
|
||||
struct s_map_default map_default;
|
||||
|
||||
int console = 0;
|
||||
int enable_spy = 0; //To enable/disable @spy commands, which consume too much cpu time when sending packets. [Skotlex]
|
||||
int enable_grf = 0; //To enable/disable reading maps from GRF files, bypassing mapcache [blackhole89]
|
||||
@ -3389,6 +3391,7 @@ int map_readallmaps (void)
|
||||
for(i = 0; i < map_num; i++) {
|
||||
size_t size;
|
||||
bool success = false;
|
||||
unsigned short idx = 0;
|
||||
|
||||
if( enable_grf ){
|
||||
// show progress
|
||||
@ -3410,14 +3413,14 @@ int map_readallmaps (void)
|
||||
}
|
||||
|
||||
// The map was not found - remove it
|
||||
if( !success ){
|
||||
if( !(idx = mapindex_name2id(map[i].name)) || !success ){
|
||||
map_delmapid(i);
|
||||
maps_removed++;
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
map[i].index = mapindex_name2id(map[i].name);
|
||||
map[i].index = idx;
|
||||
|
||||
if (uidb_get(map_db,(unsigned int)map[i].index) != NULL)
|
||||
{
|
||||
@ -3459,7 +3462,7 @@ int map_readallmaps (void)
|
||||
|
||||
// finished map loading
|
||||
ShowInfo("Successfully loaded '"CL_WHITE"%d"CL_RESET"' maps."CL_CLL"\n",map_num);
|
||||
instance_start = map_num + 1; // Next Map Index will be instances
|
||||
instance_start = map_num; // Next Map Index will be instances
|
||||
|
||||
if (maps_removed)
|
||||
ShowNotice("Maps removed: '"CL_WHITE"%d"CL_RESET"'\n",maps_removed);
|
||||
@ -4327,6 +4330,11 @@ int do_init(int argc, char *argv[])
|
||||
MSG_CONF_NAME_THA = "conf/msg_conf/map_msg_tha.conf"; // Thai
|
||||
/* Multilanguage */
|
||||
|
||||
// Default map
|
||||
safestrncpy(map_default.mapname, "prontera", MAP_NAME_LENGTH);
|
||||
map_default.x = 156;
|
||||
map_default.y = 191;
|
||||
|
||||
cli_get_options(argc,argv);
|
||||
|
||||
rnd_init();
|
||||
|
@ -498,7 +498,8 @@ enum _sp {
|
||||
|
||||
SP_IGNORE_DEF_CLASS, SP_DEF_RATIO_ATK_CLASS, SP_ADDCLASS, SP_SUBCLASS, SP_MAGIC_ADDCLASS, //2062-2066
|
||||
SP_WEAPON_COMA_CLASS, SP_IGNORE_MDEF_CLASS_RATE, SP_EXP_ADDCLASS, SP_ADD_CLASS_DROP_ITEM, //2067-2070
|
||||
SP_ADD_CLASS_DROP_ITEMGROUP, SP_ADDMAXWEIGHT, SP_ADD_ITEMGROUP_HEAL_RATE // 2071-2073
|
||||
SP_ADD_CLASS_DROP_ITEMGROUP, SP_ADDMAXWEIGHT, SP_ADD_ITEMGROUP_HEAL_RATE, // 2071-2073
|
||||
SP_HP_VANISH_RACE_RATE, SP_SP_VANISH_RACE_RATE, // 2074-2075
|
||||
};
|
||||
|
||||
enum _look {
|
||||
@ -758,6 +759,13 @@ extern char charhelp_txt[];
|
||||
|
||||
extern char wisp_server_name[];
|
||||
|
||||
struct s_map_default {
|
||||
char mapname[MAP_NAME_LENGTH];
|
||||
unsigned short x;
|
||||
unsigned short y;
|
||||
};
|
||||
extern struct s_map_default map_default;
|
||||
|
||||
/// Type of 'save_settings'
|
||||
enum save_settings_type {
|
||||
CHARSAVE_NONE = 0,
|
||||
|
286
src/map/pc.c
286
src/map/pc.c
@ -1143,8 +1143,6 @@ bool pc_authok(struct map_session_data *sd, uint32 login_id2, time_t expiration_
|
||||
sd->autobonus2[i].active = INVALID_TIMER;
|
||||
for(i = 0; i < ARRAYLENGTH(sd->autobonus3); i++)
|
||||
sd->autobonus3[i].active = INVALID_TIMER;
|
||||
for(i = 0; i < ARRAYLENGTH(sd->bonus_script); i++)
|
||||
sd->bonus_script[i].tid = INVALID_TIMER;
|
||||
|
||||
if (battle_config.item_auto_get)
|
||||
sd->state.autoloot = 10000;
|
||||
@ -1266,6 +1264,9 @@ bool pc_authok(struct map_session_data *sd, uint32 login_id2, time_t expiration_
|
||||
sd->status.cashshop_sent = false;
|
||||
|
||||
sd->last_addeditem_index = -1;
|
||||
|
||||
sd->bonus_script.head = NULL;
|
||||
sd->bonus_script.count = 0;
|
||||
|
||||
// Request all registries (auth is considered completed whence they arrive)
|
||||
intif_request_registry(sd,7);
|
||||
@ -1959,15 +1960,15 @@ int pc_disguise(struct map_session_data *sd, int class_)
|
||||
/// Show error message
|
||||
#define PC_BONUS_SHOW_ERROR(type,type2,val) { ShowError("%s: %s: Invalid %s %d.\n",__FUNCTION__,#type,#type2,(val)); break; }
|
||||
/// Check for valid Element, break & show error message if invalid Element
|
||||
#define PC_BONUS_CHK_ELEMENT(ele,bonus) { if (!CHK_ELEMENT(ele)) { PC_BONUS_SHOW_ERROR(bonus,Element,(ele)); }}
|
||||
#define PC_BONUS_CHK_ELEMENT(ele,bonus) { if (!CHK_ELEMENT((ele))) { PC_BONUS_SHOW_ERROR((bonus),Element,(ele)); }}
|
||||
/// Check for valid Race, break & show error message if invalid Race
|
||||
#define PC_BONUS_CHK_RACE(rc,bonus) { if (!CHK_RACE(rc)) { PC_BONUS_SHOW_ERROR(bonus,Race,(rc)); }}
|
||||
#define PC_BONUS_CHK_RACE(rc,bonus) { if (!CHK_RACE((rc))) { PC_BONUS_SHOW_ERROR((bonus),Race,(rc)); }}
|
||||
/// Check for valid Race2, break & show error message if invalid Race2
|
||||
#define PC_BONUS_CHK_RACE2(rc2,bonus) { if (!CHK_RACE2(rc2)) { PC_BONUS_SHOW_ERROR(bonus,Race2,(rc2)); }}
|
||||
#define PC_BONUS_CHK_RACE2(rc2,bonus) { if (!CHK_RACE2((rc2))) { PC_BONUS_SHOW_ERROR((bonus),Race2,(rc2)); }}
|
||||
/// Check for valid Class, break & show error message if invalid Class
|
||||
#define PC_BONUS_CHK_CLASS(cl,bonus) { if (!CHK_CLASS(cl)) { PC_BONUS_SHOW_ERROR(bonus,Class,(cl)); }}
|
||||
#define PC_BONUS_CHK_CLASS(cl,bonus) { if (!CHK_CLASS((cl))) { PC_BONUS_SHOW_ERROR((bonus),Class,(cl)); }}
|
||||
/// Check for valid Size, break & show error message if invalid Size
|
||||
#define PC_BONUS_CHK_SIZE(sz,bonus) { if (!CHK_MOBSIZE(sz)) { PC_BONUS_SHOW_ERROR(bonus,Size,(sz)); }}
|
||||
#define PC_BONUS_CHK_SIZE(sz,bonus) { if (!CHK_MOBSIZE((sz))) { PC_BONUS_SHOW_ERROR((bonus),Size,(sz)); }}
|
||||
|
||||
static void pc_bonus_autospell(struct s_autospell *spell, int max, short id, short lv, short rate, short flag, unsigned short card_id)
|
||||
{
|
||||
@ -3758,6 +3759,22 @@ void pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val)
|
||||
if (sd->state.lr_flag != 2)
|
||||
pc_bonus_subele(sd, (unsigned char)type2, type3, val);
|
||||
break;
|
||||
|
||||
case SP_SP_VANISH_RACE_RATE: // bonus3 bSPVanishRaceRate,r,n,x;
|
||||
PC_BONUS_CHK_RACE(type2,SP_SP_VANISH_RACE_RATE);
|
||||
if(sd->state.lr_flag != 2) {
|
||||
sd->vanish_race[type2].sp_rate += type3;
|
||||
sd->vanish_race[type2].sp_per += val;
|
||||
}
|
||||
break;
|
||||
|
||||
case SP_HP_VANISH_RACE_RATE: // bonus3 bHPVanishRaceRate,r,n,x;
|
||||
PC_BONUS_CHK_RACE(type2,SP_HP_VANISH_RACE_RATE);
|
||||
if(sd->state.lr_flag != 2) {
|
||||
sd->vanish_race[type2].hp_rate += type3;
|
||||
sd->vanish_race[type2].hp_per += val;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ShowWarning("pc_bonus3: unknown type %d %d %d %d!\n",type,type2,type3,val);
|
||||
@ -11094,80 +11111,208 @@ void pc_show_version(struct map_session_data *sd) {
|
||||
clif_displaymessage(sd->fd,buf);
|
||||
}
|
||||
|
||||
/** [Cydh]
|
||||
/**
|
||||
* Run bonus_script on player
|
||||
* @param sd
|
||||
* @author [Cydh]
|
||||
**/
|
||||
void pc_bonus_script(struct map_session_data *sd) {
|
||||
int now = gettick();
|
||||
struct linkdb_node *node = NULL, *next = NULL;
|
||||
|
||||
if (!sd || !(node = sd->bonus_script.head))
|
||||
return;
|
||||
|
||||
while (node) {
|
||||
struct s_bonus_script_entry *entry = NULL;
|
||||
next = node->next;
|
||||
|
||||
if ((entry = (struct s_bonus_script_entry *)node->data)) {
|
||||
// Only start timer for new bonus_script
|
||||
if (entry->tid == INVALID_TIMER) {
|
||||
if (entry->icon != SI_BLANK) // Gives status icon if exist
|
||||
clif_status_change(&sd->bl, entry->icon, 1, entry->tick, 1, 0, 0);
|
||||
|
||||
entry->tick += now;
|
||||
entry->tid = add_timer(entry->tick, pc_bonus_script_timer, sd->bl.id, (intptr_t)entry);
|
||||
}
|
||||
|
||||
if (entry->script)
|
||||
run_script(entry->script, 0, sd->bl.id, 0);
|
||||
else
|
||||
ShowError("pc_bonus_script: The script has been removed somewhere. \"%s\"\n", StringBuf_Value(entry->script_buf));
|
||||
}
|
||||
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add bonus_script to player
|
||||
* @param sd Player
|
||||
* @param script_str Script string
|
||||
* @param dur Duration in ms
|
||||
* @param icon SI
|
||||
* @param flag Flags @see enum e_bonus_script_flags
|
||||
* @param type 0 - None, 1 - Buff, 2 - Debuff
|
||||
* @return New created entry pointer or NULL if failed or NULL if duplicate fail
|
||||
* @author [Cydh]
|
||||
**/
|
||||
struct s_bonus_script_entry *pc_bonus_script_add(struct map_session_data *sd, const char *script_str, uint32 dur, enum si_type icon, uint16 flag, uint8 type) {
|
||||
struct script_code *script = NULL;
|
||||
struct linkdb_node *node = NULL;
|
||||
struct s_bonus_script_entry *entry = NULL;
|
||||
|
||||
if (!sd)
|
||||
return NULL;
|
||||
|
||||
if (!(script = parse_script(script_str, "bonus_script", 0, SCRIPT_IGNORE_EXTERNAL_BRACKETS))) {
|
||||
ShowError("pc_bonus_script_add: Failed to parse script '%s' (CID:%d).\n", script_str, sd->status.char_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Duplication checks
|
||||
if ((node = sd->bonus_script.head)) {
|
||||
while (node) {
|
||||
entry = (struct s_bonus_script_entry *)node->data;
|
||||
if (strcmpi(script_str, StringBuf_Value(entry->script_buf)) == 0) {
|
||||
int newdur = gettick() + dur;
|
||||
if (flag&BSF_FORCE_REPLACE && entry->tick < newdur) { // Change duration
|
||||
settick_timer(entry->tid, newdur);
|
||||
script_free_code(script);
|
||||
return NULL;
|
||||
}
|
||||
else if (flag&BSF_FORCE_DUPLICATE) // Allow duplicate
|
||||
break;
|
||||
else { // No duplicate bonus
|
||||
script_free_code(script);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
|
||||
CREATE(entry, struct s_bonus_script_entry, 1);
|
||||
|
||||
entry->script_buf = StringBuf_Malloc();
|
||||
StringBuf_AppendStr(entry->script_buf, script_str);
|
||||
entry->tid = INVALID_TIMER;
|
||||
entry->flag = flag;
|
||||
entry->icon = icon;
|
||||
entry->tick = dur; // Use duration first, on run change to expire time
|
||||
entry->type = type;
|
||||
entry->script = script;
|
||||
sd->bonus_script.count++;
|
||||
return entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove bonus_script data from player
|
||||
* @param sd: Target player
|
||||
* @param list: Bonus script entry from player
|
||||
* @author [Cydh]
|
||||
**/
|
||||
void pc_bonus_script_free_entry(struct map_session_data *sd, struct s_bonus_script_entry *entry) {
|
||||
if (entry->tid != INVALID_TIMER)
|
||||
delete_timer(entry->tid, pc_bonus_script_timer);
|
||||
|
||||
if (entry->script)
|
||||
script_free_code(entry->script);
|
||||
|
||||
if (entry->script_buf)
|
||||
StringBuf_Free(entry->script_buf);
|
||||
|
||||
if (sd) {
|
||||
if (entry->icon != SI_BLANK)
|
||||
clif_status_load(&sd->bl, entry->icon, 0);
|
||||
if (sd->bonus_script.count > 0)
|
||||
sd->bonus_script.count--;
|
||||
}
|
||||
aFree(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do final process if no entry left
|
||||
* @param sd
|
||||
**/
|
||||
static void inline pc_bonus_script_check_final(struct map_session_data *sd) {
|
||||
if (sd->bonus_script.count == 0) {
|
||||
if (sd->bonus_script.head && sd->bonus_script.head->data)
|
||||
pc_bonus_script_free_entry(sd, (struct s_bonus_script_entry *)sd->bonus_script.head->data);
|
||||
linkdb_final(&sd->bonus_script.head);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Timer for bonus_script
|
||||
* @param tid
|
||||
* @param tick
|
||||
* @param id
|
||||
* @param data
|
||||
* @author [Cydh]
|
||||
**/
|
||||
int pc_bonus_script_timer(int tid, unsigned int tick, int id, intptr_t data) {
|
||||
uint8 i = (uint8)data;
|
||||
struct map_session_data *sd;
|
||||
struct s_bonus_script_entry *entry = (struct s_bonus_script_entry *)data;
|
||||
|
||||
sd = map_id2sd(id);
|
||||
if (!sd) {
|
||||
ShowDebug("pc_bonus_script_timer: Null pointer id: %d data: %d\n",id,data);
|
||||
ShowError("pc_bonus_script_timer: Null pointer id: %d tid: %d\n", id, tid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (i >= MAX_PC_BONUS_SCRIPT || !(&sd->bonus_script[i]) || !sd->bonus_script[i].script) {
|
||||
ShowDebug("pc_bonus_script_timer: Invalid index %d\n",i);
|
||||
if (tid == INVALID_TIMER)
|
||||
return 0;
|
||||
|
||||
if (!sd->bonus_script.head || entry == NULL) {
|
||||
ShowError("pc_bonus_script_timer: Invalid entry pointer 0x%08X!\n", entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sd->bonus_script[i].icon != SI_BLANK)
|
||||
clif_status_load(&sd->bl, sd->bonus_script[i].icon, 0);
|
||||
pc_bonus_script_remove(&sd->bonus_script[i]);
|
||||
linkdb_erase(&sd->bonus_script.head, (void *)((intptr_t)entry));
|
||||
pc_bonus_script_free_entry(sd, entry);
|
||||
pc_bonus_script_check_final(sd);
|
||||
status_calc_pc(sd,SCO_NONE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** [Cydh]
|
||||
* Remove bonus_script data from player
|
||||
* @param sd: Target player
|
||||
* @param i: Bonus script index
|
||||
**/
|
||||
void pc_bonus_script_remove(struct s_bonus_script *bscript) {
|
||||
if (!bscript)
|
||||
return;
|
||||
|
||||
if (bscript->script)
|
||||
script_free_code(bscript->script);
|
||||
bscript->script = NULL;
|
||||
memset(bscript->script_str, '\0', sizeof(bscript->script_str));
|
||||
bscript->tick = 0;
|
||||
bscript->flag = 0;
|
||||
bscript->icon = SI_BLANK;
|
||||
if (bscript->tid != INVALID_TIMER)
|
||||
delete_timer(bscript->tid,pc_bonus_script_timer);
|
||||
bscript->tid = INVALID_TIMER;
|
||||
}
|
||||
|
||||
/** [Cydh]
|
||||
/**
|
||||
* Check then clear all active timer(s) of bonus_script data from player based on reason
|
||||
* @param sd: Target player
|
||||
* @param flag: Reason to remove the bonus_script. e_bonus_script_flags or e_bonus_script_types
|
||||
* @author [Cydh]
|
||||
**/
|
||||
void pc_bonus_script_clear(struct map_session_data *sd, uint16 flag) {
|
||||
uint8 i, count = 0;
|
||||
if (!sd)
|
||||
struct linkdb_node *node = NULL;
|
||||
uint16 count = 0;
|
||||
|
||||
if (!sd || !(node = sd->bonus_script.head))
|
||||
return;
|
||||
|
||||
for (i = 0; i < MAX_PC_BONUS_SCRIPT; i++) {
|
||||
if (&sd->bonus_script[i] && sd->bonus_script[i].script &&
|
||||
(sd->bonus_script[i].flag&flag || //Remove bonus script based on e_bonus_script_flags
|
||||
(sd->bonus_script[i].type && (
|
||||
(flag&BSF_REM_BUFF && sd->bonus_script[i].type == 1) || //Remove bonus script based on buff type
|
||||
(flag&BSF_REM_DEBUFF && sd->bonus_script[i].type == 2)) //Remove bonus script based on debuff type
|
||||
)))
|
||||
while (node) {
|
||||
struct linkdb_node *next = node->next;
|
||||
struct s_bonus_script_entry *entry = (struct s_bonus_script_entry *)node->data;
|
||||
|
||||
if (entry && (
|
||||
(flag == BSF_PERMANENT) || // Remove all with permanent bonus
|
||||
(!flag && !(entry->flag&BSF_PERMANENT)) || // Remove all WITHOUT permanent bonus
|
||||
(flag&entry->flag) || // Matched flag
|
||||
(flag&BSF_REM_BUFF && entry->type == 1) || // Remove buff
|
||||
(flag&BSF_REM_DEBUFF && entry->type == 2) // Remove debuff
|
||||
)
|
||||
)
|
||||
{
|
||||
if (sd->bonus_script[i].icon != SI_BLANK)
|
||||
clif_status_load(&sd->bl, sd->bonus_script[i].icon, 0);
|
||||
pc_bonus_script_remove(&sd->bonus_script[i]);
|
||||
linkdb_erase(&sd->bonus_script.head, (void *)((intptr_t)entry));
|
||||
pc_bonus_script_free_entry(sd, entry);
|
||||
count++;
|
||||
}
|
||||
|
||||
node = next;
|
||||
}
|
||||
|
||||
pc_bonus_script_check_final(sd);
|
||||
|
||||
if (count && !(flag&BSF_REM_ON_LOGOUT)) //Don't need to do this if log out
|
||||
status_calc_pc(sd,SCO_NONE);
|
||||
}
|
||||
@ -11175,25 +11320,38 @@ void pc_bonus_script_clear(struct map_session_data *sd, uint16 flag) {
|
||||
/**
|
||||
* Clear all bonus script from player
|
||||
* @param sd
|
||||
* @param permanent If true, will removes permanent bonus script.
|
||||
* @param flag &1 - Remove permanent bonus_script, &2 - Logout
|
||||
* @author [Cydh]
|
||||
*/
|
||||
void pc_bonus_script_clear_all(struct map_session_data *sd, bool permanent) {
|
||||
uint8 i, count = 0;
|
||||
if (!sd)
|
||||
**/
|
||||
void pc_bonus_script_clear_all(struct map_session_data *sd, uint8 flag) {
|
||||
struct linkdb_node *node = NULL;
|
||||
uint16 count = 0;
|
||||
|
||||
if (!sd || !(node = sd->bonus_script.head))
|
||||
return;
|
||||
|
||||
for (i = 0; i < MAX_PC_BONUS_SCRIPT; i++) {
|
||||
if (!&sd->bonus_script[i] && !sd->bonus_script[i].script)
|
||||
continue;
|
||||
if (!permanent && sd->bonus_script[i].flag&BSF_PERMANENT)
|
||||
continue;
|
||||
if (sd->bonus_script[i].icon != SI_BLANK)
|
||||
clif_status_load(&sd->bl, sd->bonus_script[i].icon, 0);
|
||||
pc_bonus_script_remove(&sd->bonus_script[i]);
|
||||
count++;
|
||||
while (node) {
|
||||
struct linkdb_node *next = node->next;
|
||||
struct s_bonus_script_entry *entry = (struct s_bonus_script_entry *)node->data;
|
||||
|
||||
if (entry && (
|
||||
!(entry->flag&BSF_PERMANENT) ||
|
||||
((flag&1) && entry->flag&BSF_PERMANENT)
|
||||
)
|
||||
)
|
||||
{
|
||||
linkdb_erase(&sd->bonus_script.head, (void *)((intptr_t)entry));
|
||||
pc_bonus_script_free_entry(sd, entry);
|
||||
count++;
|
||||
}
|
||||
|
||||
node = next;
|
||||
}
|
||||
status_calc_pc(sd,SCO_NONE);
|
||||
|
||||
pc_bonus_script_check_final(sd);
|
||||
|
||||
if (count && !(flag&2))
|
||||
status_calc_pc(sd,SCO_NONE);
|
||||
}
|
||||
|
||||
/** [Cydh]
|
||||
|
30
src/map/pc.h
30
src/map/pc.h
@ -7,6 +7,7 @@
|
||||
#include "../common/mmo.h" // JOB_*, MAX_FAME_LIST, struct fame_list, struct mmo_charstatus
|
||||
#include "../common/ers.h"
|
||||
#include "../common/timer.h" // INVALID_TIMER
|
||||
#include "../common/strlib.h"// StringBuf
|
||||
#include "map.h" // RC_ALL
|
||||
#include "atcommand.h" // AtCommandType
|
||||
#include "battle.h" // battle_config
|
||||
@ -157,13 +158,13 @@ struct s_pc_itemgrouphealrate {
|
||||
};
|
||||
|
||||
///Timed bonus 'bonus_script' struct [Cydh]
|
||||
struct s_bonus_script {
|
||||
struct s_bonus_script_entry {
|
||||
struct script_code *script;
|
||||
char script_str[MAX_BONUS_SCRIPT_LENGTH]; //Used for comparing and storing on table
|
||||
StringBuf *script_buf; //Used for comparing and storing on table
|
||||
uint32 tick;
|
||||
uint8 flag;
|
||||
char type; //0 - Ignore; 1 - Buff; 2 - Debuff
|
||||
int16 icon;
|
||||
uint16 flag;
|
||||
enum si_type icon;
|
||||
uint8 type; //0 - Ignore; 1 - Buff; 2 - Debuff
|
||||
int tid;
|
||||
};
|
||||
|
||||
@ -378,6 +379,12 @@ struct map_session_data {
|
||||
short value;
|
||||
int rate, tick;
|
||||
} def_set_race[RC_MAX], mdef_set_race[RC_MAX];
|
||||
struct s_bonus_vanish_race {
|
||||
short hp_rate, ///< Rate 0 - 10000 (100%)
|
||||
hp_per, ///< % HP vanished
|
||||
sp_rate, ///< Rate 0 - 10000 (100%)
|
||||
sp_per; ///< % SP vanished
|
||||
} vanish_race[RC_MAX];
|
||||
// zeroed structures end here
|
||||
|
||||
// manually zeroed structures start here.
|
||||
@ -603,8 +610,13 @@ struct map_session_data {
|
||||
struct vip_info vip;
|
||||
bool disableshowrate; //State to disable clif_display_pinfo(). [Cydh]
|
||||
#endif
|
||||
struct s_bonus_script bonus_script[MAX_PC_BONUS_SCRIPT]; ///Bonus Script [Cydh]
|
||||
|
||||
|
||||
/// Bonus Script [Cydh]
|
||||
struct s_bonus_script_list {
|
||||
struct linkdb_node *head; ///< Bonus script head node. data: struct s_bonus_script_entry *entry, key: (intptr_t)entry
|
||||
uint16 count;
|
||||
} bonus_script;
|
||||
|
||||
struct s_pc_itemgrouphealrate **itemgrouphealrate; /// List of Item Group Heal rate bonus
|
||||
uint8 itemgrouphealrate_count; /// Number of rate bonuses
|
||||
|
||||
@ -1128,9 +1140,9 @@ void pc_crimson_marker_clear(struct map_session_data *sd);
|
||||
void pc_show_version(struct map_session_data *sd);
|
||||
|
||||
int pc_bonus_script_timer(int tid, unsigned int tick, int id, intptr_t data);
|
||||
void pc_bonus_script_remove(struct s_bonus_script *bscript);
|
||||
void pc_bonus_script(struct map_session_data *sd);
|
||||
struct s_bonus_script_entry *pc_bonus_script_add(struct map_session_data *sd, const char *script_str, uint32 dur, enum si_type icon, uint16 flag, uint8 type);
|
||||
void pc_bonus_script_clear(struct map_session_data *sd, uint16 flag);
|
||||
void pc_bonus_script_clear_all(struct map_session_data *sd, bool permanent);
|
||||
|
||||
void pc_cell_basilica(struct map_session_data *sd);
|
||||
|
||||
|
@ -2352,12 +2352,6 @@ void script_hardcoded_constants(void) {
|
||||
script_set_constant("Option_Dragon",OPTION_DRAGON,false);
|
||||
script_set_constant("Option_Costume",OPTION_COSTUME,false);
|
||||
|
||||
/* bonus_script commands */
|
||||
script_set_constant("BSF_REM_BUFF",BSF_REM_BUFF,false);
|
||||
script_set_constant("BSF_REM_DEBUFF",BSF_REM_DEBUFF,false);
|
||||
script_set_constant("BSF_ALL",BSF_ALL,false);
|
||||
script_set_constant("BSF_CLEARALL",BSF_CLEARALL,false);
|
||||
|
||||
/* sc_start flags */
|
||||
script_set_constant("SCSTART_NONE",SCSTART_NONE,false);
|
||||
script_set_constant("SCSTART_NOAVOID",SCSTART_NOAVOID,false);
|
||||
@ -10589,7 +10583,7 @@ BUILDIN_FUNC(homunculus_evolution)
|
||||
|
||||
if(hom_is_active(sd->hd))
|
||||
{
|
||||
if (sd->hd->homunculus.intimacy > 91000)
|
||||
if (sd->hd->homunculus.intimacy >= battle_config.homunculus_evo_intimacy_need)
|
||||
hom_evolution(sd->hd);
|
||||
else
|
||||
clif_emotion(&sd->hd->bl, E_SWT);
|
||||
@ -13352,7 +13346,7 @@ int atcommand_sub(struct script_state* st,int type) {
|
||||
memcpy(&dummy_sd.bl, bl, sizeof(struct block_list));
|
||||
if (bl->type == BL_NPC)
|
||||
safestrncpy(dummy_sd.status.name, ((TBL_NPC*)bl)->name, NAME_LENGTH);
|
||||
sd->mapindex = (bl->m > 0) ? bl->m : mapindex_name2id(MAP_DEFAULT);
|
||||
sd->mapindex = (bl->m > 0) ? bl->m : mapindex_name2id(map_default.mapname);
|
||||
}
|
||||
|
||||
// Init Group ID, Level, & permissions
|
||||
@ -18881,16 +18875,20 @@ BUILDIN_FUNC(montransform) {
|
||||
* @author [Cydh]
|
||||
**/
|
||||
BUILDIN_FUNC(bonus_script) {
|
||||
uint8 i, flag = 0;
|
||||
uint16 flag = 0;
|
||||
int16 icon = SI_BLANK;
|
||||
uint32 dur;
|
||||
char type = 0;
|
||||
uint8 type = 0;
|
||||
TBL_PC* sd;
|
||||
const char *script_str = NULL;
|
||||
struct script_code *script = NULL;
|
||||
struct s_bonus_script_entry *entry = NULL;
|
||||
|
||||
if (script_hasdata(st,7))
|
||||
sd = map_charid2sd(script_getnum(st,7));
|
||||
if (script_hasdata(st,7)) {
|
||||
if (!(sd = map_charid2sd(script_getnum(st,7)))) {
|
||||
ShowError("buildin_bonus_script: Player CID=%d is not found.\n", script_getnum(st,7));
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
}
|
||||
else
|
||||
sd = script_rid2sd(st);
|
||||
|
||||
@ -18899,46 +18897,28 @@ BUILDIN_FUNC(bonus_script) {
|
||||
|
||||
script_str = script_getstr(st,2);
|
||||
dur = 1000 * abs(script_getnum(st,3));
|
||||
FETCH(4,flag);
|
||||
FETCH(5,type);
|
||||
FETCH(6,icon);
|
||||
FETCH(4, flag);
|
||||
FETCH(5, type);
|
||||
FETCH(6, icon);
|
||||
|
||||
// No Script string, No Duration!
|
||||
if (script_str[0] == '\0' || !dur) {
|
||||
//ShowWarning("buildin_bonus_script: Invalid script. Skipping...\n");
|
||||
ShowError("buildin_bonus_script: Invalid! Script: \"%s\". Duration: %d\n", script_str, dur);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
//Skip duplicate entry
|
||||
ARR_FIND(0,MAX_PC_BONUS_SCRIPT,i,&sd->bonus_script[i] && sd->bonus_script[i].script_str && strcmp(sd->bonus_script[i].script_str,script_str) == 0);
|
||||
if (i < MAX_PC_BONUS_SCRIPT) {
|
||||
//ShowWarning("buildin_bonus_script: Duplicate entry with bonus '%d'. Skipping...\n",i);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
if (!(script = parse_script(script_str,"bonus_script",0,1))) {
|
||||
ShowWarning("buildin_bonus_script: Failed to parse script '%s' (cid:%d). Skipping...\n",script_str,sd->status.char_id);
|
||||
if (strlen(script_str) >= MAX_BONUS_SCRIPT_LENGTH) {
|
||||
ShowError("buildin_bonus_script: Script string to long: \"%s\".\n", script_str);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
//Find the empty slot
|
||||
ARR_FIND(0,MAX_PC_BONUS_SCRIPT,i,!sd->bonus_script[i].script);
|
||||
if (i >= MAX_PC_BONUS_SCRIPT) {
|
||||
ShowWarning("buildin_itemscript: Maximum script_bonus is reached (cid:%d max: %d). Skipping...\n",sd->status.char_id,MAX_PC_BONUS_SCRIPT);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
if (icon <= SI_BLANK || icon >= SI_MAX)
|
||||
icon = SI_BLANK;
|
||||
|
||||
if ((entry = pc_bonus_script_add(sd, script_str, dur, (enum si_type)icon, flag, type))) {
|
||||
linkdb_insert(&sd->bonus_script.head, (void *)((intptr_t)entry), entry);
|
||||
status_calc_pc(sd,SCO_NONE);
|
||||
}
|
||||
|
||||
//Add the script data
|
||||
memcpy(sd->bonus_script[i].script_str,script_str,strlen(script_str)+1);
|
||||
sd->bonus_script[i].script = script;
|
||||
sd->bonus_script[i].tick = gettick() + dur;
|
||||
sd->bonus_script[i].flag = flag;
|
||||
sd->bonus_script[i].type = type;
|
||||
sd->bonus_script[i].icon = icon;
|
||||
|
||||
if (sd->bonus_script[i].icon != SI_BLANK) //Gives status icon if exist
|
||||
clif_status_change(&sd->bl,sd->bonus_script[i].icon,1,dur,1,0,0);
|
||||
|
||||
status_calc_pc(sd,SCO_NONE);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -18951,7 +18931,7 @@ BUILDIN_FUNC(bonus_script) {
|
||||
*/
|
||||
BUILDIN_FUNC(bonus_script_clear) {
|
||||
TBL_PC* sd;
|
||||
bool flag = 0;
|
||||
bool flag = false;
|
||||
|
||||
if (script_hasdata(st,2))
|
||||
flag = script_getnum(st,2);
|
||||
@ -18964,7 +18944,7 @@ BUILDIN_FUNC(bonus_script_clear) {
|
||||
if (sd == NULL)
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
|
||||
pc_bonus_script_clear_all(sd,flag); /// Don't remove permanent script
|
||||
pc_bonus_script_clear(sd,(flag ? BSF_PERMANENT : BSF_REM_ALL));
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -704,7 +704,7 @@ bool skill_isNotOk_hom(uint16 skill_id, struct homun_data *hd)
|
||||
|
||||
switch(skill_id) {
|
||||
case MH_LIGHT_OF_REGENE: //must be cordial
|
||||
if (hom_get_intimacy_grade(hd) != 4) {
|
||||
if (hom_get_intimacy_grade(hd) < HOMGRADE_CORDIAL) {
|
||||
if (hd->master)
|
||||
clif_skill_fail(hd->master, skill_id, USESKILL_FAIL_RELATIONGRADE, 0);
|
||||
return true;
|
||||
@ -2118,7 +2118,7 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
|
||||
case HVAN_EXPLOSION:
|
||||
if(src->type == BL_HOM){
|
||||
TBL_HOM *hd = (TBL_HOM*)src;
|
||||
hd->homunculus.intimacy = 200;
|
||||
hd->homunculus.intimacy = (skill_id == HFLI_SBR44) ? 200 : 100; // hom_intimacy_grade2intimacy(HOMGRADE_HATE_WITH_PASSION)
|
||||
if (hd->master)
|
||||
clif_send_homdata(hd->master,SP_INTIMATE,hd->homunculus.intimacy/100);
|
||||
}
|
||||
@ -3622,7 +3622,7 @@ static int skill_check_condition_mercenary(struct block_list *bl, int skill, int
|
||||
switch( skill )
|
||||
{
|
||||
case HFLI_SBR44:
|
||||
if( hd->homunculus.intimacy <= 200 )
|
||||
if( hd->homunculus.intimacy <= 200 ) // hom_intimacy_grade2intimacy(HOMGRADE_HATE_WITH_PASSION)
|
||||
return 0;
|
||||
break;
|
||||
case HVAN_EXPLOSION:
|
||||
@ -10228,8 +10228,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
struct block_list *s_bl = battle_get_master(src);
|
||||
if(s_bl) sc_start(src, s_bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv));
|
||||
sc_start2(src, src, type, 100, skill_lv, hd->homunculus.level, skill_get_time(skill_id, skill_lv));
|
||||
hd->homunculus.intimacy = 25100; //change to neutral (can't be cast if < 750)
|
||||
if(sd) clif_send_homdata(sd, SP_INTIMATE, hd->homunculus.intimacy); //refresh intimacy info
|
||||
hd->homunculus.intimacy = hom_intimacy_grade2intimacy(HOMGRADE_NEUTRAL); //change to neutral
|
||||
if(sd) clif_send_homdata(sd, SP_INTIMATE, hd->homunculus.intimacy/100); //refresh intimacy info
|
||||
skill_blockhomun_start(hd, skill_id, skill_get_cooldown(skill_id, skill_lv));
|
||||
}
|
||||
break;
|
||||
|
@ -1638,21 +1638,22 @@ int status_heal(struct block_list *bl,int64 hhp,int64 hsp, int flag)
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies percentage based damage to a unit
|
||||
* If a mob is killed this way and there is no src, no EXP/Drops will be awarded
|
||||
* Applies percentage based damage to a unit.
|
||||
* If a mob is killed this way and there is no src, no EXP/Drops will be awarded.
|
||||
* @param src: Object initiating HP/SP modification [PC|MOB|PET|HOM|MER|ELEM]
|
||||
* @param target: Object to modify HP/SP
|
||||
* @param hp_rate: Percentage of HP to modify
|
||||
* @param sp_rate: Percentage of SP to modify
|
||||
* @param flag: \n
|
||||
* 0: Heal target \n
|
||||
* 2: Target must not die from subtraction
|
||||
* 1: Use status_damage \n
|
||||
* 2: Use status_damage and make sure target must not die from subtraction
|
||||
* @return hp+sp through status_heal()
|
||||
*/
|
||||
int status_percent_change(struct block_list *src,struct block_list *target,signed char hp_rate, signed char sp_rate, int flag)
|
||||
int status_percent_change(struct block_list *src, struct block_list *target, int8 hp_rate, int8 sp_rate, uint8 flag)
|
||||
{
|
||||
struct status_data *status;
|
||||
unsigned int hp =0, sp = 0;
|
||||
unsigned int hp = 0, sp = 0;
|
||||
|
||||
status = status_get_status_data(target);
|
||||
|
||||
@ -1661,15 +1662,11 @@ int status_percent_change(struct block_list *src,struct block_list *target,signe
|
||||
if (hp_rate > 99)
|
||||
hp = status->hp;
|
||||
else if (hp_rate > 0)
|
||||
hp = status->hp>10000?
|
||||
hp_rate*(status->hp/100):
|
||||
((int64)hp_rate*status->hp)/100;
|
||||
hp = apply_rate(status->hp, hp_rate);
|
||||
else if (hp_rate < -99)
|
||||
hp = status->max_hp;
|
||||
else if (hp_rate < 0)
|
||||
hp = status->max_hp>10000?
|
||||
(-hp_rate)*(status->max_hp/100):
|
||||
((int64)-hp_rate*status->max_hp)/100;
|
||||
hp = (apply_rate(status->hp, -hp_rate));
|
||||
if (hp_rate && !hp)
|
||||
hp = 1;
|
||||
|
||||
@ -1679,29 +1676,29 @@ int status_percent_change(struct block_list *src,struct block_list *target,signe
|
||||
if (sp_rate > 99)
|
||||
sp = status->sp;
|
||||
else if (sp_rate > 0)
|
||||
sp = ((int64)sp_rate*status->sp)/100;
|
||||
sp = apply_rate(status->sp, sp_rate);
|
||||
else if (sp_rate < -99)
|
||||
sp = status->max_sp;
|
||||
else if (sp_rate < 0)
|
||||
sp = ((int64)-sp_rate)*status->max_sp/100;
|
||||
sp = (apply_rate(status->sp, -sp_rate));
|
||||
if (sp_rate && !sp)
|
||||
sp = 1;
|
||||
|
||||
// Ugly check in case damage dealt is too much for the received args of
|
||||
// status_heal / status_damage. [Skotlex]
|
||||
if (hp > INT_MAX) {
|
||||
hp -= INT_MAX;
|
||||
hp -= INT_MAX;
|
||||
if (flag)
|
||||
status_damage(src, target, INT_MAX, 0, 0, (!src||src==target?5:1));
|
||||
else
|
||||
status_heal(target, INT_MAX, 0, 0);
|
||||
status_heal(target, INT_MAX, 0, 0);
|
||||
}
|
||||
if (sp > INT_MAX) {
|
||||
if (sp > INT_MAX) {
|
||||
sp -= INT_MAX;
|
||||
if (flag)
|
||||
status_damage(src, target, 0, INT_MAX, 0, (!src||src==target?5:1));
|
||||
else
|
||||
status_heal(target, 0, INT_MAX, 0);
|
||||
status_heal(target, 0, INT_MAX, 0);
|
||||
}
|
||||
if (flag)
|
||||
return status_damage(src, target, hp, sp, 0, (!src||src==target?5:1));
|
||||
@ -2972,6 +2969,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
|
||||
+ sizeof(sd->subele2)
|
||||
+ sizeof(sd->def_set_race)
|
||||
+ sizeof(sd->mdef_set_race)
|
||||
+ sizeof(sd->vanish_race)
|
||||
);
|
||||
|
||||
memset (&sd->bonus, 0, sizeof(sd->bonus));
|
||||
@ -3181,13 +3179,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
|
||||
run_script(data->script,0,sd->bl.id,0);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_PC_BONUS_SCRIPT; i++) { //Process script Bonus [Cydh]
|
||||
if (!(&sd->bonus_script[i]) || !sd->bonus_script[i].script)
|
||||
continue;
|
||||
if (sd->bonus_script[i].tid == INVALID_TIMER) //Just add timer only for new attached script
|
||||
sd->bonus_script[i].tid = add_timer(sd->bonus_script[i].tick,pc_bonus_script_timer,sd->bl.id,i);
|
||||
run_script(sd->bonus_script[i].script,0,sd->bl.id,0);
|
||||
}
|
||||
pc_bonus_script(sd);
|
||||
|
||||
if( sd->pd ) { // Pet Bonus
|
||||
struct pet_data *pd = sd->pd;
|
||||
@ -3720,6 +3712,7 @@ int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt)
|
||||
#ifdef RENEWAL
|
||||
amotion = hd->homunculusDB->baseASPD;
|
||||
amotion = amotion - amotion * (status->dex + hom->dex_value) / 1000 - (status->agi + hom->agi_value) * amotion / 250;
|
||||
status->def = status->mdef = 0;
|
||||
#else
|
||||
skill_lv = hom->level / 10 + status->vit / 5;
|
||||
status->def = cap_value(skill_lv, 0, 99);
|
||||
|
@ -1746,23 +1746,25 @@ enum e_status_change_start_flags {
|
||||
|
||||
///Enum for bonus_script's flag [Cydh]
|
||||
enum e_bonus_script_flags {
|
||||
BSF_REM_ON_DEAD = 0x001, ///Removed when dead
|
||||
BSF_REM_ON_DISPELL = 0x002, ///Removed by Dispell
|
||||
BSF_REM_ON_CLEARANCE = 0x004, ///Removed by Clearance
|
||||
BSF_REM_ON_LOGOUT = 0x008, ///Removed when player logged out
|
||||
BSF_REM_ON_BANISHING_BUSTER = 0x010, ///Removed by Banishing Buster
|
||||
BSF_REM_ON_REFRESH = 0x020, ///Removed by Refresh
|
||||
BSF_REM_ON_LUXANIMA = 0x040, ///Removed by Luxanima
|
||||
BSF_REM_ON_MADOGEAR = 0x080, ///Removed when Madogear is activated or deactivated
|
||||
BSF_REM_ON_DAMAGED = 0x100, ///Removed when receive damage
|
||||
BSF_PERMANENT = 0x200, ///Cannot be removed by sc_end SC_ALL
|
||||
BSF_REM_ON_DEAD = 0x001, ///< Removed when dead
|
||||
BSF_REM_ON_DISPELL = 0x002, ///< Removed by Dispell
|
||||
BSF_REM_ON_CLEARANCE = 0x004, ///< Removed by Clearance
|
||||
BSF_REM_ON_LOGOUT = 0x008, ///< Removed when player logged out
|
||||
BSF_REM_ON_BANISHING_BUSTER = 0x010, ///< Removed by Banishing Buster
|
||||
BSF_REM_ON_REFRESH = 0x020, ///< Removed by Refresh
|
||||
BSF_REM_ON_LUXANIMA = 0x040, ///< Removed by Luxanima
|
||||
BSF_REM_ON_MADOGEAR = 0x080, ///< Removed when Madogear is activated or deactivated
|
||||
BSF_REM_ON_DAMAGED = 0x100, ///< Removed when receive damage
|
||||
BSF_PERMANENT = 0x200, ///< Cannot be removed by sc_end SC_ALL
|
||||
|
||||
// These flags better in the last of everything
|
||||
BSF_REM_BUFF = 0x1000, ///Remove positive buff
|
||||
BSF_REM_DEBUFF = 0x2000, ///Remove negative buff
|
||||
// These flags cannot be stacked, BSF_FORCE_REPLACE has highest priority to check if YOU force to add both
|
||||
BSF_FORCE_REPLACE = 0x400, ///< Force to replace duplicated script by expanding the duration
|
||||
BSF_FORCE_DUPLICATE = 0x800, ///< Force to add duplicated script
|
||||
|
||||
BSF_ALL = 0x0FFF|BSF_REM_BUFF|BSF_REM_DEBUFF,
|
||||
BSF_CLEARALL = BSF_ALL&~BSF_PERMANENT,
|
||||
// These flags aren't part of 'bonus_script' scripting flags
|
||||
BSF_REM_ALL = 0x0, ///< Remove all bonus script
|
||||
BSF_REM_BUFF = 0x4000, ///< Remove positive buff if battle_config.debuff_on_logout&1
|
||||
BSF_REM_DEBUFF = 0x8000, ///< Remove negative buff if battle_config.debuff_on_logout&2
|
||||
};
|
||||
|
||||
///Enum for status_get_hpbonus and status_get_spbonus
|
||||
@ -1934,7 +1936,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 dhp,int
|
||||
#define status_zap(bl, hp, sp) status_damage(NULL, bl, hp, sp, 0, 1)
|
||||
//Define for standard HP/SP skill-related cost triggers (mobs require no HP/SP to use skills)
|
||||
int64 status_charge(struct block_list* bl, int64 hp, int64 sp);
|
||||
int status_percent_change(struct block_list *src,struct block_list *target,signed char hp_rate, signed char sp_rate, int flag);
|
||||
int status_percent_change(struct block_list *src, struct block_list *target, int8 hp_rate, int8 sp_rate, uint8 flag);
|
||||
//Easier handling of status_percent_change
|
||||
#define status_percent_heal(bl, hp_rate, sp_rate) status_percent_change(NULL, bl, -(hp_rate), -(sp_rate), 0)
|
||||
#define status_percent_damage(src, target, hp_rate, sp_rate, kill) status_percent_change(src, target, hp_rate, sp_rate, (kill)?1:2)
|
||||
|
@ -3169,6 +3169,10 @@ int unit_free(struct block_list *bl, clr_type clrtype)
|
||||
sd->num_quests = sd->avail_quests = 0;
|
||||
}
|
||||
|
||||
// Clearing...
|
||||
if (sd->bonus_script.head)
|
||||
pc_bonus_script_clear(sd, BSF_REM_ALL);
|
||||
|
||||
pc_itemgrouphealrate_clear(sd);
|
||||
break;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user