Compare commits

..

58 Commits

Author SHA1 Message Date
Aleos
1e01f6448f Merge branch 'master' into hotfix/issue4984 2023-01-09 13:05:01 -05:00
Lemongrass3110
913519ed50 Fixed online_char_db (#7539)
Added a missing map entry assignment from an invalid DBMap ensure conversion.

Fixes #7538

Thanks to @MaouDaiou and @zdurexz
2023-01-09 16:09:36 +01:00
Lemongrass3110
e64c5bce35 Fixed item restrictions for noreturn
Fixes #7537

Thanks to @mazvi
2023-01-09 15:12:31 +01:00
Lemongrass3110
4836d8e77a Added latest constants and names 2023-01-06 22:58:50 +01:00
Lemongrass3110
4fb6740ebf Replaced DBMap usage in char-server (#7514)
Co-authored-by: Aleos <aleos89@users.noreply.github.com>
2023-01-06 20:29:01 +01:00
Lemongrass3110
c9aaf540bf Added reloadbarterdb (#7530)
Fixes #7520

Thanks to @attackjom
2023-01-06 00:23:25 +01:00
Balfear
134bfbe986 Added new guild UI features (#6285)
Co-authored-by: Aleos <aleos89@users.noreply.github.com>
Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
Co-authored-by: Null Ragnarok Relation <59070443+iberryRO@users.noreply.github.com>
2023-01-05 23:39:30 +01:00
Aleos
7323800838 Fixes shadowing for private variables (#7531)
* Fixes #7508.
* Follow C++ convention for private variable declaration.
Thanks to @Lemongrass3110 and @idk-whoami!
2023-01-05 12:30:39 -05:00
Lemongrass3110
9dda166c0e Converted cash shop database to YAML (#6299)
Co-authored-by: Atemo <Atemo@users.noreply.github.com>
Co-authored-by: Aleos <aleos89@users.noreply.github.com>
2023-01-05 18:30:07 +01:00
Aleos
503b57dbef Add extra validation checks for map coordinates (#7526)
* Add extra validation checks for map coordinates
* Adds some extra validation checks for map coordinates when parsed in YAML.
2023-01-04 14:30:29 -05:00
Atemo
ea3464598d Added support for new maps up to december 21 2022 (#7525) 2023-01-04 15:19:57 +01:00
Jittapan Pluemsumran
857a34832f Prevent opening vending UI multiple times (#6430)
Prevent opening vending UI multiple times in one vending session.
Discard cart modification packet when the player is in a 'can't act' state.

Fixes #3408

Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
2023-01-04 15:19:26 +01:00
Atemo
3958a96771 Added sp_rudus4, dungeon level 200 (#7334)
* Added mobs db, mobs spawn and quests related to sp_rudus4

Thanks to @Dieby, @secretdataz !

Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
2023-01-03 22:51:34 +01:00
Aleos
b867a2171f Adds char_server config for clearing parties (#7523)
* Adds a character server config to clear empty parties at start up.
* The commented code was hidden in the source and is pretty useless unless you are digging for it.
2023-01-03 16:22:30 -05:00
Atemo
936abe13eb Doc update (#7517)
* Updated the description of instance_id and getitemname script commands
2023-01-03 20:55:55 +01:00
Lemongrass3110
1361e9c1df Enabled conformance mode in MSVS (#7513) 2023-01-03 18:50:16 +01:00
Lemongrass3110
64228cd18f Fixed bAddMonsterDropItemGroup (#7516)
Fixes #7515

Thanks to @AcDczZ
2022-12-30 22:03:55 +01:00
Atemo
d0b51d91a0 Fixed an issue with mail (#7518)
* mail should accept card with ID 0 (no card) when the parameter card is provided
2022-12-29 23:36:55 +01:00
Atemo
fa0253342a Added items etc, combo, equipment (#7507)
Added items Enchant
Added items reform
Small correction of a combo

Thanks to @fab10Carvalho for the review
2022-12-29 02:05:57 +01:00
Aleos
42eccbb1bf Merge branch 'master' into hotfix/issue4984 2022-12-24 00:35:02 -05:00
aleos
50bd9cdfbe Fixes statuses with tick intervals
* Adds a new storage location for these tick types.
* Reverts some of the tick_total variable assignments.
* Adjusts sc_start to account for 64 bit tick values.
Thanks to @eppc0330!
2022-12-23 16:22:35 -05:00
idk-whoami
323a541074 Item db updated (#7485)
* Implementations + corrections of a bunch of items
2022-12-21 15:12:18 +01:00
Aleos
70d729ecf8 Fixes GitHub Workflow Concurrency flag (#7505)
* Do not cancel master workflow.
2022-12-20 19:53:39 -05:00
Lemongrass3110
39d5a02a31 Initial release of adventure agency (#7224)
Thanks to @Dia, @OptimusM, @Balferian and @ecdarreola
2022-12-21 01:17:42 +01:00
Atemo
3d5cd57c54 Added new etc/equipment/enchant up to december 2022 (#7489)
* Implemented new equipments and etc
* Updated item_enchant.yml

Thanks to @attackjom !
2022-12-21 00:47:23 +01:00
Lemongrass3110
2c4ee64b59 Start refactoring the core to C++ (#7303) 2022-12-20 23:37:31 +01:00
Aleos
ef4d52fd7b Adds official Wand of Hermode clear list (#7494)
* Wand of Hermode has a unique status clear list separate from the list other skills use.
* Adds RemoveOnHermode status flag to identify statuses that can be removed from Wand of Hermode.
Thanks to @mrjnumber1 and @Lemongrass3110!
2022-12-20 17:05:27 -05:00
Lemongrass3110
3bfead228e Additional safeguards for upgrade_20221218.sql
Thanks to @mazvi for his help.
2022-12-20 20:20:05 +01:00
Singe Horizontal
9e476cce31 Fixed specialeffect with npc names (#7502)
Fixes #7501

Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
2022-12-20 17:27:59 +01:00
Lemongrass3110
448d8febfa Follow up to 3b71f77
Thanks to @Atemo
2022-12-20 14:09:58 +01:00
Balfear
3b71f77c27 pc_isUseitem: update flywings list (#7487)
Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
2022-12-20 14:03:59 +01:00
idk-whoami
5b8d0ee6a5 Update EDP requirements (#7463)
Fixes #7458

Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
2022-12-19 12:19:30 +01:00
Balfear
9b6a4de288 Roulette: Bonus item reward (#7427)
Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
Co-authored-by: Aleos <aleos89@users.noreply.github.com>
2022-12-19 00:15:02 +01:00
Balfear
817b86d5e1 Roulette: Bonus item reward (#7427)
Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
Co-authored-by: Aleos <aleos89@users.noreply.github.com>
2022-12-19 00:14:38 +01:00
Atemo
0e948b5f9a Fixed a potential issue with getmapxy (#7498) 2022-12-18 13:15:57 +01:00
Lemongrass3110
eda702ca2c Fixed gaps in random options (#7449)
Fixes #7447

Thanks to @Abszoluto
2022-12-18 02:52:18 +01:00
Lemongrass3110
d1e184e46c Initial version of cashmall (#7450)
Introduces the cashmall
Added Cachua_Coupon exchange NPC
Enabled Devil Enchant Master and moved to Cash Mall
Moved Mergician
Added Basta, Mighty Hammer and Brock
Moved Shadow Blacksmith
Added Cash Hair Stylist
Added a feature switch for Stylist UI
Updated Hair Stylist

Thanks to @aleos89, @Atemo and @eppc0330!

Co-authored-by: aleos <aleos89@users.noreply.github.com>
Co-authored-by: Atemo <Atemo@users.noreply.github.com>
2022-12-18 00:39:50 +01:00
Pokye
ee91ab507a Item DB update (#7451)
* Added Missing Items
* Correction of several item names
* Added missing hateffects
2022-12-17 23:47:54 +01:00
Lemongrass3110
165e0d668f Fixed dynamic NPC timeout (#7497)
Fixes #7473
Updates the last interaction time on end; and close;
Additionally added the official dynamic NPC result packet.

Thanks to @eppc0330
2022-12-17 22:33:19 +01:00
idk-whoami
93cf18736a Update warper npc (#7413)
* Updated and added new warps entries up to episode 19
2022-12-17 14:15:02 +01:00
Atemo
b862aed75c Small correction for SHC_SAVAGE_IMPACT and SHC_DANCING_KNIFE skills (#7496)
* Small correction for SHC_SAVAGE_IMPACT and SHC_DANCING_KNIFE skills
* SHC_SAVAGE_IMPACT should move the player from 1 cell to the target, between the target and the player
* SHC_DANCING_KNIFE shouldn't force the player to stand
* The behaviour should be the same for GC_CROSSIMPACT than SHC_SAVAGE_IMPACT

Thanks to @aleos89 @Lemongrass3110 !
2022-12-17 14:08:09 +01:00
Lemongrass3110
ae686056a0 Added CodeQL analysis (#7208)
Adds CodeQL analysis because LGTM was disabled and removed.
2022-12-16 22:34:59 +01:00
Lemongrass3110
4d734abc53 Cleaned up monster skill status checks (#7495)
Fixes 4 more warnings introduced in 1f4c068
2022-12-16 21:56:55 +01:00
Atemo
ef602d98cb Multiple dynamic npc (#7486)
* Vectorize npc_id_dynamic to support multiple dynamic npc with different ids

Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>

Thanks to @dimasshotta and @eppc0330 !
2022-12-16 21:22:31 +01:00
idk-whoami
20dedc7918 Update items first aid starter pack (#7493) 2022-12-16 20:24:47 +01:00
Singe Horizontal
8eac71f57f Cleaned struct tokens for map_session_data and status_change (#7490)
Fixes #7492
2022-12-16 19:16:29 +01:00
aleos
5676a45908 Resolves compile errors 2022-12-14 15:08:50 -05:00
Aleos
1c1bb9892c Merge branch 'master' into hotfix/issue4984 2022-12-14 14:41:56 -05:00
Aleos
da375a04c1 Adds battle config mob_respawn_time (#7312)
* Adjusts the minimum respawn time of a monster to be 1 second as it is officially.
* Adds a battle config to allow for easy adjustment.
* Monsters that don't define a delay1 for permanent spawn scripts are defaulted to 5 seconds.
Thanks to @mrjnumber1, @vstumpf, @Lemongrass3110, and @Atemo!
Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
2022-12-14 14:17:41 -05:00
Vincent Stumpf
1f4c068c39 Refactor status change entries (#7356)
* Make map_session_data a class, call constructor/destructor on alloc/free

* add getSCE

* add create, delete, clear SCE

* Use getSCE, make data access private

* add a cache for last-fetched status
2022-12-13 23:47:53 -08:00
Aleos
ee2dcf816e New macro detection features (#7359)
* Adds battle config macro_detection_punishment to ban or jail characters.
* Adds battle config macro_detection_punishment_time to adjust the duration of ban/jail for players who fail the captcha challenges.
* Adds script command macro_detector which invokes the captcha challenge.
* General cleanups to the jail functions to remove duplicate code.
* General cleanups to the macro punishment calls to remove duplicate code.
* Ending SC_JAILED will now properly remove the jail status rather than trying to reset the timer to 1 second resolving any possibility of players getting stuck.
Thanks to @Lemongrass3110!
2022-12-13 15:44:42 -05:00
Singe Horizontal
5a533a7a12 Fixes drop rate for size-moded mobs (#7482)
* Fixes #7481.
* Restores correct drop rate for spawned size-modified monsters so that they read the current memory instead of the database value if changed.
2022-12-13 08:23:00 -05:00
Aleos
3545a9c82f Minor corrections to SQL readme (#7484)
* Cleans up a bit of the SQL readme so it's less confusing.
Thanks to @emmamarshall451!
2022-12-12 15:09:24 -05:00
Aleos
c951f68250 Merge branch 'master' into hotfix/issue4984 2022-12-09 14:54:37 -05:00
aleos
9440ba8929 Minor clif fix
* tick_total is not a timer ID and thus a lookup is unnecessary.
2022-12-08 08:11:08 -05:00
aleos
9ff252d2b1 Merge branch 'master' into hotfix/issue4984 2022-12-07 13:12:16 -05:00
aleos
7a345b85cb Cleanups
Thanks to @Lemongrass3110!
2020-08-13 10:37:43 -04:00
aleos
da8d77bfc1 Corrects status icon timer after relog
* Fixes #4984.
* Resolves status icon timers not properly showing the difference of remaining/total time when a player relogs.
* Fixes status icon timers going into negative values.
Thanks to @attackjom!
2020-08-03 10:20:07 -04:00
206 changed files with 29923 additions and 9696 deletions

91
.github/workflows/analysis_codeql.yml vendored Normal file
View File

@@ -0,0 +1,91 @@
name: Analyse servers with CodeQL
# analysis_codeql.yml
concurrency:
group: ${{ github.repository }}-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
on:
push:
branches:
- master
pull_request:
paths:
# Always trigger all Github Actions if an action or something CI related was changed
- '.github/workflows/**'
- 'tools/ci/**'
# This workflow should run when a file in a source directory has been modified.
- 'src/**'
- '3rdparty/**'
jobs:
analyze:
# Github Actions checks for '[ci skip]', '[skip ci]', '[no ci]', '[skip actions]', or '[actions skip]' but not a hyphenated version.
# It's a catch-all incase a Pull Request has been opened and someone is on auto-pilot.
if: "!contains(github.event.head_commit.message, 'ci-skip')"
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
# The ubuntu-latest label currently points to ubuntu-20.04.
# Available: ubuntu-22.04, ubuntu-20.04
os: [ubuntu-latest]
# Older versions of GCC are not available via unaltered aptitude repo lists.
gcc: ['10']
# We run build checks for both Renewal and PRE-Renewal
mode: ['PRE','RE']
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
languages: cpp
# Trigger security and quality findings
# https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# TODO: Resolve the issues and then enable it again
#queries: +security-and-quality
# A simple 'yes' and 'no' can be confusing, so we use names to display in the current job then convert them for use in the compiler.
- name: Variable Parsing - PRE
if: ${{ matrix.mode == 'PRE' }}
run: |
echo "PRERE=yes" >> $GITHUB_ENV
- name: Variable Parsing - RE
if: ${{ matrix.mode == 'RE' }}
run: |
echo "PRERE=no" >> $GITHUB_ENV
- name: Update & Install packages
# Ubuntu runners already have most of the packages rAthena requires to build.
# https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-Readme.md
run: |
sudo apt update
sudo apt install zlib1g-dev libpcre3-dev gcc-${{ matrix.gcc }} g++-${{ matrix.gcc }}
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
#- name: Autobuild
# uses: github/codeql-action/autobuild@v2
# ✏️ If the Autobuild fails above, remove it and uncomment the following
# three lines and modify them (or add more) to build your code if your
# project uses a compiled language
- name: Command - configure
env:
CONFIGURE_FLAGS: 'CC=gcc-${{ matrix.gcc }} CXX=g++-${{ matrix.gcc }} --enable-prere=${{ env.PRERE }} --enable-buildbot=yes'
run: ./configure $CONFIGURE_FLAGS
- name: Command - make clean
run: make clean
- name: Command - make server
run: make server
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

View File

@@ -3,7 +3,7 @@ name: Build servers with Clang
concurrency:
group: ${{ github.repository }}-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
on:
push:

View File

@@ -3,7 +3,7 @@ name: Build servers with CMake
concurrency:
group: ${{ github.repository }}-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
on:
push:

View File

@@ -3,7 +3,7 @@ name: Build servers with GCC
concurrency:
group: ${{ github.repository }}-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
on:
push:

View File

@@ -3,7 +3,7 @@ name: Build servers in Pre-Renewal and Renewal
concurrency:
group: ${{ github.repository }}-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
on:
push:

View File

@@ -3,7 +3,7 @@ name: Build servers with MSVS
concurrency:
group: ${{ github.repository }}-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
on:
push:

View File

@@ -3,7 +3,7 @@ name: Build servers with different packet versions
concurrency:
group: ${{ github.repository }}-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
on:
push:

View File

@@ -3,7 +3,7 @@ name: Build servers in VIP mode
concurrency:
group: ${{ github.repository }}-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
on:
push:

View File

@@ -6,7 +6,7 @@ name: Validate NPC Scripts and DB Changes
concurrency:
group: ${{ github.repository }}-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
on:
push:

View File

@@ -158,3 +158,14 @@ macro_detection_retry: 3
// Amount of time in milliseconds before the macro detection will fail and the user will be banned.
// Official: 60000
macro_detection_timeout: 60000
// Macro Detector punishment type
// 0 - Ban
// 1 - Jail
// Official: 0
macro_detection_punishment: 0
// Macro Detector punishment duration
// Amount of time in minutes that the punishment type is active for. Use 0 for infinite.
// Official: 0
macro_detection_punishment_time: 0

View File

@@ -67,6 +67,10 @@ feature.bgqueue: on
// Requires: 2014-10-22bRagexe or later
feature.roulette: on
// Roulette bonus reward
// Multiply amount by 2 if the reward item ID is the same as bonus item ID
feature.roulette_bonus_reward: on
// Achievement (Note 1)
// Requires: 2015-05-13aRagexe or later
feature.achievement: on
@@ -142,3 +146,7 @@ feature.dynamicnpc_direction: no
// like from SHIFT+Click from player's inventory/cart/equipment window.
// Requires: 2010-00-00RagexeRE or later
feature.itemlink: on
// Stylist UI (Note 1)
// Requires: 2015-11-04 or later
feature.stylist: on

View File

@@ -297,3 +297,8 @@ achievement_mob_share: no
// Should slaves teleport back to their master if they get too far during chase? (Note 1)
// Default (Official): no
slave_stick_with_master: no
// Absolute minimum respawn time in milliseconds of a monster.
// Also used in delaying the spawning of guardians when a guild is not loaded.
// Default (Official): 1000
mob_respawn_time: 1000

View File

@@ -198,6 +198,9 @@ char_del_restriction: 3
// Uncomment to customize the restriction
//allowed_job_flag: 3
// Should parties that don't have any members be cleared from the party_db table at start up?
clear_parties: no
// Folder that contains the database files.
db_path: db

View File

@@ -147,8 +147,6 @@ item_table: item_db
renewal-item_table: item_db_re
item2_table: item_db2
renewal-item2_table: item_db2_re
item_cash_table: item_cash_db
item_cash2_table: item_cash_db2
mob_table: mob_db
renewal-mob_table: mob_db_re
mob2_table: mob_db2
@@ -158,6 +156,7 @@ renewal-mob_skill_table: mob_skill_db_re
mob_skill2_table: mob_skill_db2
renewal-mob_skill2_table: mob_skill_db2_re
mapreg_table: mapreg
partybookings_table: party_bookings
sales_table: sales
vending_table: vendings
vending_items_table: vending_items
@@ -166,7 +165,7 @@ roulette_table: db_roulette
guild_storage_log: guild_storage_log
// Web Database Tables
// NOTE: The web server reads the login (login) and char (guild) tables, so it needs
// NOTE: The web server reads the login (login) and char (party,guild) tables and map (party_bookings), so it needs
// the ability to connect to those databases.
guild_emblems: guild_emblems
user_configs: user_configs

View File

@@ -1517,6 +1517,9 @@ map: bl_grass
map: bl_lava
map: bl_ice
map: bl_death
map: bl_soul
map: bl_temple
map: bl_venom
// Clock Tower: Unknown Basement
map: clock_01
@@ -1535,6 +1538,11 @@ map: 1@vrcas
map: 1@vrev
map: 1@vrgen
map: 1@vrpo
map: 1@vrac1
map: 1@vrac2
map: 1@vrclo
map: 1@vrhha
map: 2@vrclo
// ??
map: 1@pdb
@@ -1558,5 +1566,9 @@ map: hero_out4
map: hero_tra
map: herosria
// Level 260 Expansion
map: mjo_wst01
map: ra_pol01
//------------------------- Clone Maps ---------------------------
//------------------------- Extra Maps ---------------------------

View File

@@ -927,7 +927,10 @@
// Enchant UI
829: Enchanting is not possible for your item's enchant grade.
//830-899 free
// @reloadbarterdb
830: Barter database has been reloaded.
//831-899 free
//------------------------------------
// More atcommands message

View File

@@ -26,174 +26,18 @@
# Map Map name to be considered as the castle map.
# Name Name of the castle (used by scripts and guardian name tags).
# Npc NPC unique name to invoke ::OnGuildBreak on, when a occupied castle is abandoned during guild break.
# Type The WoE type this castle belongs to. (Default: First_Edition)
# ClientId Client side ID of the castle. (Default: 0)
# WarpEnabled If the warp to the castle is enabled. (Default: false)
# WarpX X coordinate to warp to. (Default: 0)
# WarpY Y coordinate to warp to. (Default: 0)
# WarpCost Zeny cost to use the warp. (Default: 100)
# WarpCostSiege Zeny cost to use the warp during WoE. (Default: 100000)
###########################################################################
Header:
Type: CASTLE_DB
Version: 1
Body:
# WOE FE castle
- Id: 0
Map: aldeg_cas01
Name: Neuschwanstein
#Name: Noisyubantian
Npc: Agit#aldeg_cas01
- Id: 1
Map: aldeg_cas02
Name: Hohenschwangau
#Name: Hohensyubangawoo
Npc: Agit#aldeg_cas02
- Id: 2
Map: aldeg_cas03
Name: Nuernberg
#Name: Nyirenverk
Npc: Agit#aldeg_cas03
- Id: 3
Map: aldeg_cas04
Name: Wuerzburg
#Name: Byirtsburi
Npc: Agit#aldeg_cas04
- Id: 4
Map: aldeg_cas05
Name: Rothenburg
#Name: Rotenburk
Npc: Agit#aldeg_cas05
- Id: 5
Map: gefg_cas01
Name: Repherion
#Name: Reprion
Npc: Agit#gefg_cas01
- Id: 6
Map: gefg_cas02
Name: Eeyolbriggar
#Name: Yolbriger
Npc: Agit#gefg_cas02
- Id: 7
Map: gefg_cas03
Name: Yesnelph
#Name: Isinlife
Npc: Agit#gefg_cas03
- Id: 8
Map: gefg_cas04
Name: Bergel
#Name: Berigel
Npc: Agit#gefg_cas04
- Id: 9
Map: gefg_cas05
Name: Mersetzdeitz
#Name: Melsedetsu
Npc: Agit#gefg_cas05
- Id: 10
Map: payg_cas01
Name: Bright Arbor
#Name: Mingting
Npc: Agit#payg_cas01
- Id: 11
Map: payg_cas02
Name: Scarlet Palace
#Name: Tiantan
Npc: Agit#payg_cas02
- Id: 12
Map: payg_cas03
Name: Holy Shadow
#Name: Fuying
Npc: Agit#payg_cas03
- Id: 13
Map: payg_cas04
Name: Sacred Altar
#Name: Honglou
Npc: Agit#payg_cas04
- Id: 14
Map: payg_cas05
Name: Bamboo Grove Hill
#Name: Zhulinxian
Npc: Agit#payg_cas05
- Id: 15
Map: prtg_cas01
Name: Kriemhild
#Name: Creamhilt
Npc: Agit#prtg_cas01
- Id: 16
Map: prtg_cas02
Name: Swanhild
#Name: Sbanhealt
Npc: Agit#prtg_cas02
- Id: 17
Map: prtg_cas03
Name: Fadhgridh
#Name: Lazrigees
Npc: Agit#prtg_cas03
- Id: 18
Map: prtg_cas04
Name: Skoegul
#Name: Squagul
Npc: Agit#prtg_cas04
- Id: 19
Map: prtg_cas05
Name: Gondul
#Name: Guindull
Npc: Agit#prtg_cas05
# WOE NGuild castle
- Id: 20
Map: nguild_alde
Name: Earth
Npc: Agit_N01
- Id: 21
Map: nguild_gef
Name: Air
Npc: Agit_N02
- Id: 22
Map: nguild_pay
Name: Water
Npc: Agit_N03
- Id: 23
Map: nguild_prt
Name: Fire
Npc: Agit_N04
# WOE SE castle
- Id: 24
Map: schg_cas01
Name: Himinn
Npc: Manager#schg_cas01
- Id: 25
Map: schg_cas02
Name: Andlangr
Npc: Manager#schg_cas02
- Id: 26
Map: schg_cas03
Name: Viblainn
Npc: Manager#schg_cas03
- Id: 27
Map: schg_cas04
Name: Hljod
Npc: Manager#schg_cas04
- Id: 28
Map: schg_cas05
Name: Skidbladnir
Npc: Manager#schg_cas05
- Id: 29
Map: arug_cas01
Name: Mardol
Npc: Manager#arug_cas01
- Id: 30
Map: arug_cas02
Name: Cyr
Npc: Manager#arug_cas02
- Id: 31
Map: arug_cas03
Name: Horn
Npc: Manager#arug_cas03
- Id: 32
Map: arug_cas04
Name: Gefn
Npc: Manager#arug_cas04
- Id: 33
Map: arug_cas05
Name: Bandis
Npc: Manager#arug_cas05
Version: 2
Footer:
Imports:

View File

@@ -26,8 +26,15 @@
# Map Map name to be considered as the castle map.
# Name Name of the castle (used by scripts and guardian name tags).
# Npc NPC unique name to invoke ::OnGuildBreak on, when a occupied castle is abandoned during guild break.
# Type The WoE type this castle belongs to. (Default: First_Edition)
# ClientId Client side ID of the castle. (Default: 0)
# WarpEnabled If the warp to the castle is enabled. (Default: false)
# WarpX X coordinate to warp to. (Default: 0)
# WarpY Y coordinate to warp to. (Default: 0)
# WarpCost Zeny cost to use the warp. (Default: 100)
# WarpCostSiege Zeny cost to use the warp during WoE. (Default: 100000)
###########################################################################
Header:
Type: CASTLE_DB
Version: 1
Version: 2

View File

@@ -0,0 +1,33 @@
# This file is a part of rAthena.
# Copyright(C) 2022 rAthena Development Team
# https://rathena.org - https://github.com/rathena
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
###########################################################################
# Item Cash Database
###########################################################################
#
# Item Cash Settings
#
###########################################################################
# - Tab Cash shop tab. Available tabs are New, Hot, Limited, Rental, Permanent, Scrolls, Consumables, Other, Sale.
# Items: List of possible items.
# - Item Item name.
# Price Item cost in cash points (#CASHPOINTS).
###########################################################################
Header:
Type: ITEM_CASH_DB
Version: 1

View File

@@ -1,19 +0,0 @@
// Cash Shop Database
// Contains the items sold in the ingame cash shop.
//
// Structure of Database:
// Type,ItemID,Price
//
// Type:
// 0: New
// 1: Hot
// 2: Limited
// 3: Rental
// 4: Gear
// 5: Buff
// 6: Heal
// 7: Other
// 8: Sale
//
// Price:
// Item cost, in cash points (#CASHPOINTS).

37
db/item_cash.yml Normal file
View File

@@ -0,0 +1,37 @@
# This file is a part of rAthena.
# Copyright(C) 2022 rAthena Development Team
# https://rathena.org - https://github.com/rathena
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
###########################################################################
# Item Cash Database
###########################################################################
#
# Item Cash Settings
#
###########################################################################
# - Tab Cash shop tab. Available tabs are New, Hot, Limited, Rental, Permanent, Scrolls, Consumables, Other, Sale.
# Items: List of possible items.
# - Item Item name.
# Price Item cost in cash points (#CASHPOINTS).
###########################################################################
Header:
Type: ITEM_CASH_DB
Version: 1
Footer:
Imports:
- Path: db/import/item_cash.yml

Binary file not shown.

View File

@@ -1200,6 +1200,16 @@ hero_out3
hero_out4
hero_tra
herosria
1@vrac1
1@vrac2
1@vrclo
1@vrhha
2@vrclo
bl_soul
bl_temple
bl_venom
mjo_wst01
ra_pol01
//======================================================================================
// - Other/Extra maps -

View File

@@ -26,8 +26,242 @@
# Map Map name to be considered as the castle map.
# Name Name of the castle (used by scripts and guardian name tags).
# Npc NPC unique name to invoke ::OnGuildBreak on, when a occupied castle is abandoned during guild break.
# Type The WoE type this castle belongs to. (Default: First_Edition)
# ClientId Client side ID of the castle. (Default: 0)
# WarpEnabled If the warp to the castle is enabled. (Default: false)
# WarpX X coordinate to warp to. (Default: 0)
# WarpY Y coordinate to warp to. (Default: 0)
# WarpCost Zeny cost to use the warp. (Default: 100)
# WarpCostSiege Zeny cost to use the warp during WoE. (Default: 100000)
###########################################################################
Header:
Type: CASTLE_DB
Version: 1
Version: 2
Body:
# WOE FE castle
- Id: 0
Map: aldeg_cas01
Name: Neuschwanstein
#Name: Noisyubantian
Npc: Agit#aldeg_cas01
Type: First_Edition
ClientId: 6
- Id: 1
Map: aldeg_cas02
Name: Hohenschwangau
#Name: Hohensyubangawoo
Npc: Agit#aldeg_cas02
Type: First_Edition
ClientId: 7
- Id: 2
Map: aldeg_cas03
Name: Nuernberg
#Name: Nyirenverk
Npc: Agit#aldeg_cas03
Type: First_Edition
ClientId: 8
- Id: 3
Map: aldeg_cas04
Name: Wuerzburg
#Name: Byirtsburi
Npc: Agit#aldeg_cas04
Type: First_Edition
ClientId: 9
- Id: 4
Map: aldeg_cas05
Name: Rothenburg
#Name: Rotenburk
Npc: Agit#aldeg_cas05
Type: First_Edition
ClientId: 10
- Id: 5
Map: gefg_cas01
Name: Repherion
#Name: Reprion
Npc: Agit#gefg_cas01
Type: First_Edition
ClientId: 11
- Id: 6
Map: gefg_cas02
Name: Eeyolbriggar
#Name: Yolbriger
Npc: Agit#gefg_cas02
Type: First_Edition
ClientId: 12
- Id: 7
Map: gefg_cas03
Name: Yesnelph
#Name: Isinlife
Npc: Agit#gefg_cas03
Type: First_Edition
ClientId: 13
- Id: 8
Map: gefg_cas04
Name: Bergel
#Name: Berigel
Npc: Agit#gefg_cas04
Type: First_Edition
ClientId: 14
- Id: 9
Map: gefg_cas05
Name: Mersetzdeitz
#Name: Melsedetsu
Npc: Agit#gefg_cas05
Type: First_Edition
ClientId: 15
- Id: 10
Map: payg_cas01
Name: Bright Arbor
#Name: Mingting
Npc: Agit#payg_cas01
Type: First_Edition
ClientId: 16
- Id: 11
Map: payg_cas02
Name: Scarlet Palace
#Name: Tiantan
Npc: Agit#payg_cas02
Type: First_Edition
ClientId: 17
- Id: 12
Map: payg_cas03
Name: Holy Shadow
#Name: Fuying
Npc: Agit#payg_cas03
Type: First_Edition
ClientId: 18
- Id: 13
Map: payg_cas04
Name: Sacred Altar
#Name: Honglou
Npc: Agit#payg_cas04
Type: First_Edition
ClientId: 19
- Id: 14
Map: payg_cas05
Name: Bamboo Grove Hill
#Name: Zhulinxian
Npc: Agit#payg_cas05
Type: First_Edition
ClientId: 20
- Id: 15
Map: prtg_cas01
Name: Kriemhild
#Name: Creamhilt
Npc: Agit#prtg_cas01
Type: First_Edition
ClientId: 1
- Id: 16
Map: prtg_cas02
Name: Swanhild
#Name: Sbanhealt
Npc: Agit#prtg_cas02
Type: First_Edition
ClientId: 2
- Id: 17
Map: prtg_cas03
Name: Fadhgridh
#Name: Lazrigees
Npc: Agit#prtg_cas03
Type: First_Edition
ClientId: 3
- Id: 18
Map: prtg_cas04
Name: Skoegul
#Name: Squagul
Npc: Agit#prtg_cas04
Type: First_Edition
ClientId: 4
- Id: 19
Map: prtg_cas05
Name: Gondul
#Name: Guindull
Npc: Agit#prtg_cas05
Type: First_Edition
ClientId: 5
# WOE NGuild castle
- Id: 20
Map: nguild_alde
Name: Earth
Npc: Agit_N01
Type: First_Edition
- Id: 21
Map: nguild_gef
Name: Air
Npc: Agit_N02
Type: First_Edition
- Id: 22
Map: nguild_pay
Name: Water
Npc: Agit_N03
Type: First_Edition
- Id: 23
Map: nguild_prt
Name: Fire
Npc: Agit_N04
Type: First_Edition
# WOE SE castle
- Id: 24
Map: schg_cas01
Name: Himinn
Npc: Manager#schg_cas01
Type: Second_Edition
ClientId: 26
- Id: 25
Map: schg_cas02
Name: Andlangr
Npc: Manager#schg_cas02
Type: Second_Edition
ClientId: 27
- Id: 26
Map: schg_cas03
Name: Viblainn
Npc: Manager#schg_cas03
Type: Second_Edition
ClientId: 28
- Id: 27
Map: schg_cas04
Name: Hljod
Npc: Manager#schg_cas04
Type: Second_Edition
ClientId: 29
- Id: 28
Map: schg_cas05
Name: Skidbladnir
Npc: Manager#schg_cas05
Type: Second_Edition
ClientId: 30
- Id: 29
Map: arug_cas01
Name: Mardol
Npc: Manager#arug_cas01
Type: Second_Edition
ClientId: 21
- Id: 30
Map: arug_cas02
Name: Cyr
Npc: Manager#arug_cas02
Type: Second_Edition
ClientId: 22
- Id: 31
Map: arug_cas03
Name: Horn
Npc: Manager#arug_cas03
Type: Second_Edition
ClientId: 23
- Id: 32
Map: arug_cas04
Name: Gefn
Npc: Manager#arug_cas04
Type: Second_Edition
ClientId: 24
- Id: 33
Map: arug_cas05
Name: Bandis
Npc: Manager#arug_cas05
Type: Second_Edition
ClientId: 25

View File

@@ -1,19 +0,0 @@
// Cash Shop Database
// Contains the items sold in the ingame cash shop.
//
// Structure of Database:
// Type,ItemID,Price
//
// Type:
// 0: New
// 1: Hot
// 2: Limited
// 3: Rental
// 4: Gear
// 5: Buff
// 6: Heal
// 7: Other
// 8: Sale
//
// Price:
// Item cost, in cash points (#CASHPOINTS).

View File

@@ -7433,3 +7433,45 @@ Body:
Rate: 1
- Item: Gold_Tiara_
Rate: 1
- Group: MF_NOTELEPORT
SubGroups:
- SubGroup: 0
List:
- Item: Wing_Of_Fly
- Item: Giant_Fly_Wing
- Item: N_Fly_Wing
- Item: E_Giant_Fly_Wing
- Item: F_Giant_Fly_Wing
- Group: MF_NORETURN
SubGroups:
- SubGroup: 0
List:
- Item: Wing_Of_Butterfly
- Item: N_Butterfly_Wing
- Item: Dun_Tele_Scroll1
- Item: Dun_Tele_Scroll2
- Item: Dun_Tele_Scroll3
- Item: E_Dun_Tele_Scroll1
- Item: F_Dun_Tele_Scroll1
- Item: WOB_Rune
- Item: E_WOB_Rune
- Item: F_WOB_Rune
- Item: WOB_Schwaltz
- Item: E_WOB_Schwaltz
- Item: F_WOB_Schwaltz
- Item: WOB_Rachel
- Item: E_WOB_Rachel
- Item: F_WOB_Rachel
- Item: WOB_Local
- Item: E_WOB_Local
- Item: F_WOB_Local
- Item: Siege_Teleport_Scroll
- Item: Siege_Teleport_Scroll2
- Item: E_Siege_Teleport_Scroll
- Group: GIANT_FLY_WING
SubGroups:
- SubGroup: 0
List:
- Item: Giant_Fly_Wing
- Item: E_Giant_Fly_Wing
- Item: F_Giant_Fly_Wing

View File

@@ -245,6 +245,7 @@ Body:
BossResist: true
NoSave: true
NoClearance: true
RemoveOnHermode: true
Fail:
Refresh: true
Inspiration: true
@@ -273,6 +274,7 @@ Body:
BossResist: true
Debuff: true
NoSaveInfinite: true
RemoveOnHermode: true
EndOnStart:
Freeze: true
Stone: true
@@ -296,6 +298,7 @@ Body:
Quicken: true
Flags:
RequireWeapon: true
RemoveOnHermode: true
Fail:
Decreaseagi: true
- Status: Concentrate
@@ -306,6 +309,7 @@ Body:
Dex: true
Flags:
FailedMado: true
RemoveOnHermode: true
Fail:
Quagmire: true
- Status: Hiding
@@ -324,11 +328,10 @@ Body:
OnTouch: true
StopAttacking: true
RemoveOnDamaged: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
NoBanishingBuster: true
NoDispell: true
NoClearance: true
NoSave: true
EndOnStart:
Closeconfine: true
Closeconfine2: true
@@ -357,6 +360,7 @@ Body:
Atk_Ele: true
Flags:
RemoveOnUnequipWeapon: true
RemoveOnHermode: true
EndOnStart:
Aspersio: true
Fireweapon: true
@@ -369,6 +373,8 @@ Body:
- Status: Poisonreact
Icon: EFST_POISONREACT
DurationLookup: AS_POISONREACT
Flags:
RemoveOnHermode: true
- Status: Quagmire
Icon: EFST_QUAGMIRE
DurationLookup: WZ_QUAGMIRE
@@ -381,6 +387,7 @@ Body:
NoSave: true
NoClearance: true
Debuff: true
RemoveOnHermode: true
Fail:
Speedup1: true
EndOnStart:
@@ -408,6 +415,7 @@ Body:
Angelus: true
Flags:
SendOption: true
RemoveOnHermode: true
- Status: Blessing
Icon: EFST_BLESSING
DurationLookup: AL_BLESSING
@@ -418,6 +426,7 @@ Body:
Flags:
BossResist: true
TaekwonAngel: true
RemoveOnHermode: true
- Status: Signumcrucis
Icon: EFST_CRUCIS
DurationLookup: AL_CRUCIS
@@ -437,6 +446,7 @@ Body:
Flags:
FailedMado: true
TaekwonAngel: true
RemoveOnHermode: true
Fail:
Quagmire: true
EndOnStart:
@@ -452,6 +462,7 @@ Body:
BossResist: true
NoSave: true
Debuff: true
RemoveOnHermode: true
Fail:
Speedup1: true
EndOnStart:
@@ -470,6 +481,7 @@ Body:
DurationLookup: PR_SLOWPOISON
Flags:
NoClearance: true
RemoveOnHermode: true
- Status: Impositio
Icon: EFST_IMPOSITIO
DurationLookup: PR_IMPOSITIO
@@ -477,6 +489,7 @@ Body:
Watk: true
Flags:
SuperNoviceAngel: true
RemoveOnHermode: true
EndOnStart:
Impositio: true
- Status: Suffragium
@@ -484,6 +497,7 @@ Body:
DurationLookup: PR_SUFFRAGIUM
Flags:
SuperNoviceAngel: true
RemoveOnHermode: true
- Status: Aspersio
Icon: EFST_ASPERSIO
DurationLookup: PR_ASPERSIO
@@ -491,6 +505,7 @@ Body:
Atk_Ele: true
Flags:
RemoveOnUnequipWeapon: true
RemoveOnHermode: true
EndOnStart:
Encpoison: true
Fireweapon: true
@@ -509,11 +524,13 @@ Body:
NoSave: true
NoClearance: true
#RemoveOnUnequipArmor: true
RemoveOnHermode: true
- Status: Kyrie
Icon: EFST_KYRIE
DurationLookup: PR_KYRIE
Flags:
SuperNoviceAngel: true
RemoveOnHermode: true
EndOnStart:
Assumptio: true
- Status: Magnificat
@@ -525,6 +542,7 @@ Body:
FailedMado: true
NoSave: true
SuperNoviceAngel: true
RemoveOnHermode: true
- Status: Gloria
Icon: EFST_GLORIA
DurationLookup: PR_GLORIA
@@ -532,11 +550,13 @@ Body:
Luk: true
Flags:
SuperNoviceAngel: true
RemoveOnHermode: true
- Status: Aeterna
Icon: EFST_LEXAETERNA
DurationLookup: PR_LEXAETERNA
Flags:
NoSave: true
RemoveOnHermode: true
Fail:
Stone: true
Freeze: true
@@ -548,6 +568,7 @@ Body:
Flags:
MadoCancel: true
RequireWeapon: true
RemoveOnHermode: true
Fail:
Quagmire: true
Decreaseagi: true
@@ -556,6 +577,7 @@ Body:
DurationLookup: BS_WEAPONPERFECT
Flags:
MadoCancel: true
RemoveOnHermode: true
- Status: Overthrust
Icon: EFST_OVERTHRUST
DurationLookup: BS_OVERTHRUST
@@ -563,6 +585,7 @@ Body:
OverThrust: true
Flags:
MadoCancel: true
RemoveOnHermode: true
Fail:
Maxoverthrust: true
- Status: Maximizepower
@@ -572,6 +595,7 @@ Body:
Regen: true
Flags:
MadoCancel: true
RemoveOnHermode: true
- Status: Trickdead
Icon: EFST_TRICKDEAD
DurationLookup: NV_TRICKDEAD
@@ -590,7 +614,8 @@ Body:
RemoveOnDamaged: true
NoSave: true
NoClearance: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
RemoveOnHermode: true
EndOnStart:
Dancing: true
- Status: Loud
@@ -600,11 +625,14 @@ Body:
Str: true
Flags:
MadoCancel: true
RemoveOnHermode: true
- Status: Energycoat
Icon: EFST_ENERGYCOAT
DurationLookup: MG_ENERGYCOAT
Opt3:
EnergyCoat: true
Flags:
RemoveOnHermode: true
- Status: Brokenarmor
Icon: EFST_BROKENARMOR
DurationLookup: NPC_ARMORBRAKE
@@ -656,12 +684,14 @@ Body:
Flags:
NoClearance: true
OverlapIgnoreLevel: true
RemoveOnHermode: true
- Status: Aspdpotion2
Icon: EFST_ATTHASTE_POTION3
CalcFlags:
Aspd: true
Flags:
OverlapIgnoreLevel: true
RemoveOnHermode: true
- Status: Aspdpotion3
Icon: EFST_ATTHASTE_INFINITY
CalcFlags:
@@ -669,6 +699,7 @@ Body:
Flags:
NoClearance: true
OverlapIgnoreLevel: true
RemoveOnHermode: true
- Status: Speedup0
Icon: EFST_MOVHASTE_HORSE
CalcFlags:
@@ -686,6 +717,7 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnHermode: true
- Status: Atkpotion
Icon: EFST_PLUSATTACKPOWER
CalcFlags:
@@ -694,6 +726,7 @@ Body:
NoRemoveOnDead: true
NoClearance: true
OverlapIgnoreLevel: true
RemoveOnHermode: true
- Status: Matkpotion
Icon: EFST_PLUSMAGICPOWER
CalcFlags:
@@ -702,6 +735,7 @@ Body:
NoRemoveOnDead: true
NoClearance: true
OverlapIgnoreLevel: true
RemoveOnHermode: true
- Status: Wedding
States:
NoAttack: true
@@ -732,8 +766,7 @@ Body:
NoDispell: true
NoBanishingBuster: true
NoClearance: true
RemoveOnMapWarp: true
NoSave: true
RemoveOnChangeMap: true
MinDuration: 5000
- Status: Keeping
DurationLookup: NPC_KEEPING
@@ -745,6 +778,8 @@ Body:
CalcFlags:
Mdef: true
Def: true
Flags:
RemoveOnHermode: true
- Status: Stripweapon
Icon: EFST_NOEQUIPWEAPON
DurationLookup: RG_STRIPWEAPON
@@ -757,6 +792,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
NoSave: true
RemoveOnHermode: true
- Status: Stripshield
Icon: EFST_NOEQUIPSHIELD
DurationLookup: RG_STRIPSHIELD
@@ -769,6 +805,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
NoSave: true
RemoveOnHermode: true
- Status: Striparmor
Icon: EFST_NOEQUIPARMOR
DurationLookup: RG_STRIPARMOR
@@ -781,6 +818,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
NoSave: true
RemoveOnHermode: true
- Status: Striphelm
Icon: EFST_NOEQUIPHELM
DurationLookup: RG_STRIPHELM
@@ -793,6 +831,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
NoSave: true
RemoveOnHermode: true
- Status: Cp_Weapon
Icon: EFST_PROTECTWEAPON
DurationLookup: AM_CP_WEAPON
@@ -802,6 +841,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
RemoveChemicalProtect: true
RemoveOnHermode: true
- Status: Cp_Shield
Icon: EFST_PROTECTSHIELD
DurationLookup: AM_CP_SHIELD
@@ -811,6 +851,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
RemoveChemicalProtect: true
RemoveOnHermode: true
- Status: Cp_Armor
Icon: EFST_PROTECTARMOR
DurationLookup: AM_CP_ARMOR
@@ -820,6 +861,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
RemoveChemicalProtect: true
RemoveOnHermode: true
- Status: Cp_Helm
Icon: EFST_PROTECTHELM
DurationLookup: AM_CP_HELM
@@ -829,18 +871,21 @@ Body:
NoBanishingBuster: true
NoClearance: true
RemoveChemicalProtect: true
RemoveOnHermode: true
- Status: Autoguard
Icon: EFST_AUTOGUARD
DurationLookup: CR_AUTOGUARD
Flags:
NoClearance: true
RequireShield: true
RemoveOnHermode: true
- Status: Reflectshield
Icon: EFST_REFLECTSHIELD
DurationLookup: CR_REFLECTSHIELD
Flags:
NoClearance: true
RequireShield: true
RemoveOnHermode: true
EndOnStart:
Reflectdamage: true
- Status: Splasher
@@ -853,6 +898,7 @@ Body:
All: true
Flags:
NoSave: true
RemoveOnHermode: true
- Status: Defender
Icon: EFST_DEFENDER
DurationLookup: CR_DEFENDER
@@ -861,11 +907,13 @@ Body:
Aspd: true
Flags:
RequireShield: true
RemoveOnHermode: true
- Status: Magicrod
Icon: EFST_MAGICROD
DurationLookup: SA_MAGICROD
Flags:
NoSave: true
RemoveOnHermode: true
- Status: Spellbreaker
Flags:
NoWarning: true
@@ -899,6 +947,7 @@ Body:
Flags:
FailedMado: true
RequireWeapon: true
RemoveOnHermode: true
Fail:
Quagmire: true
- Status: Autocounter
@@ -953,6 +1002,7 @@ Body:
Debuff: true
NoClearance: true
NoSave: true
RemoveOnHermode: true
- Status: Combo
Flags:
NoClearbuff: true
@@ -965,8 +1015,7 @@ Body:
States:
NoMove: true
Flags:
RemoveOnMapWarp: true
NoSave: true
RemoveOnChangeMap: true
- Status: Bladestop
Icon: EFST_BLADESTOP
DurationLookup: MO_BLADESTOP
@@ -983,7 +1032,8 @@ Body:
NoClearbuff: true
NoSave: true
NoClearance: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
RemoveOnHermode: true
- Status: Fireweapon
Icon: EFST_PROPERTYFIRE
DurationLookup: SA_FLAMELAUNCHER
@@ -1052,6 +1102,7 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnHermode: true
- Status: Deluge
Icon: EFST_GROUNDMAGIC
DurationLookup: SA_DELUGE
@@ -1111,6 +1162,7 @@ Body:
Flags:
NoSave: true
RequireWeapon: true
RemoveOnHermode: true
- Status: Parrying
Icon: EFST_PARRYING
DurationLookup: LK_PARRYING
@@ -1118,6 +1170,7 @@ Body:
NoSave: true
NoClearance: true
RequireWeapon: true
RemoveOnHermode: true
- Status: Concentration
Icon: EFST_LKCONCENTRATION
DurationLookup: LK_CONCENTRATION
@@ -1131,6 +1184,7 @@ Body:
Quicken: true
Flags:
NoSave: true
RemoveOnHermode: true
- Status: Tensionrelax
Icon: EFST_TENSIONRELAX
DurationLookup: LK_TENSIONRELAX
@@ -1139,6 +1193,7 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnHermode: true
- Status: Berserk
Icon: EFST_BERSERK
DurationLookup: LK_BERSERK
@@ -1179,6 +1234,7 @@ Body:
Aspd: true
Flags:
NoSave: true
RemoveOnHermode: true
- Status: Assumptio
Icon: EFST_ASSUMPTIO
DurationLookup: HP_ASSUMPTIO
@@ -1187,6 +1243,8 @@ Body:
EndOnStart:
Kyrie: true
Kaite: true
Flags:
RemoveOnHermode: true
- Status: Basilica
DurationLookup: HP_BASILICA
States:
@@ -1196,7 +1254,8 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
RemoveOnHermode: true
- Status: Guildaura
Flags:
NoDispell: true
@@ -1209,6 +1268,7 @@ Body:
Matk: true
Flags:
NoSave: true
RemoveOnHermode: true
EndOnStart:
Magicpower: true
- Status: Edp
@@ -1234,6 +1294,7 @@ Body:
Flags:
FailedMado: true
NoSave: true
RemoveOnHermode: true
Fail:
Quagmire: true
- Status: Windwalk
@@ -1245,6 +1306,7 @@ Body:
Flags:
FailedMado: true
NoSave: true
RemoveOnHermode: true
Fail:
Quagmire: true
- Status: Meltdown
@@ -1288,11 +1350,10 @@ Body:
OnTouch: true
StopAttacking: true
RemoveOnDamaged: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
NoBanishingBuster: true
NoDispell: true
NoClearance: true
NoSave: true
- Status: Rejectsword
Icon: EFST_SWORDREJECT
DurationLookup: ST_REJECTSWORD
@@ -1309,8 +1370,7 @@ Body:
Opt3:
Marionette: true
Flags:
RemoveOnMapWarp: true
NoSave: true
RemoveOnChangeMap: true
Fail:
Marionette: true
- Status: Marionette2
@@ -1326,8 +1386,7 @@ Body:
Opt3:
Marionette: true
Flags:
RemoveOnMapWarp: true
NoSave: true
RemoveOnChangeMap: true
Fail:
Marionette2: true
- Status: Changeundead
@@ -1341,6 +1400,7 @@ Body:
Debuff: true
NoClearance: true
NoSave: true
RemoveOnHermode: true
EndOnStart:
Blessing: true
Increaseagi: true
@@ -1356,6 +1416,7 @@ Body:
NoSave: true
NoClearance: true
Debuff: true
RemoveOnHermode: true
- Status: Mindbreaker
Icon: EFST_MINDBREAKER
DurationLookup: PF_MINDBREAKER
@@ -1365,6 +1426,7 @@ Body:
Flags:
NoSave: true
Debuff: true
RemoveOnHermode: true
EndOnStart:
Freeze: true
Stone: true
@@ -1374,6 +1436,7 @@ Body:
DurationLookup: PF_MEMORIZE
Flags:
NoSave: true
RemoveOnHermode: true
- Status: Fogwall
Icon: EFST_FOGWALL
DurationLookup: PF_FOGWALL
@@ -1381,6 +1444,7 @@ Body:
BossResist: true
NoSave: true
NoClearance: true
RemoveOnHermode: true
- Status: Spiderweb
Icon: EFST_SPIDERWEB
DurationLookup: PF_SPIDERWEB
@@ -1401,8 +1465,9 @@ Body:
DurationLookup: CR_DEVOTION
Flags:
NoSave: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
OverlapIgnoreLevel: true
RemoveOnHermode: true
EndOnEnd:
Autoguard: true
Defender: true
@@ -1410,6 +1475,8 @@ Body:
Endure: true
- Status: Sacrifice
DurationLookup: PA_SACRIFICE
Flags:
RemoveOnHermode: true
- Status: Steelbody
Icon: EFST_STEELBODY
DurationLookup: MO_STEELBODY
@@ -1422,6 +1489,7 @@ Body:
Speed: true
Flags:
NoSave: true
RemoveOnHermode: true
Opt3:
SteelBody: true
- Status: Orcish
@@ -1485,7 +1553,8 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
RemoveOnHermode: true
- Status: Shadowweapon
Icon: EFST_PROPERTYDARK
DurationLookup: TK_SEVENWIND
@@ -1494,6 +1563,7 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnHermode: true
EndOnStart:
Encpoison: true
Aspersio: true
@@ -1511,6 +1581,7 @@ Body:
MadoCancel: true
NoSave: true
RequireWeapon: true
RemoveOnHermode: true
Fail:
Quagmire: true
Decreaseagi: true
@@ -1522,6 +1593,7 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnHermode: true
EndOnStart:
Encpoison: true
Aspersio: true
@@ -1539,6 +1611,7 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnHermode: true
EndOnStart:
Kaahi: true
- Status: Kaupe
@@ -1547,6 +1620,7 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnHermode: true
- Status: Onehand
Icon: EFST_ONEHANDQUICKEN
DurationLookup: KN_ONEHAND
@@ -1558,6 +1632,7 @@ Body:
NoSave: true
NoClearance: true
RequireWeapon: true
RemoveOnHermode: true
Fail:
Decreaseagi: true
EndOnStart:
@@ -1570,6 +1645,7 @@ Body:
DurationLookup: ST_PRESERVE
Flags:
NoSave: true
RemoveOnHermode: true
- Status: Battleorders
Icon: EFST_GDSKILL_BATTLEORDER
DurationLookup: GD_BATTLEORDER
@@ -1593,6 +1669,7 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnHermode: true
- Status: Gravitation
Icon: EFST_GRAVITATION
DurationLookup: HW_GRAVITATION
@@ -1607,6 +1684,7 @@ Body:
BossResist: true
NoSave: true
NoClearance: true
RemoveOnHermode: true
- Status: Maxoverthrust
Icon: EFST_OVERTHRUSTMAX
DurationLookup: WS_OVERTHRUSTMAX
@@ -1615,6 +1693,7 @@ Body:
Flags:
MadoCancel: true
NoSave: true
RemoveOnHermode: true
EndOnStart:
Overthrust: true
- Status: Longing
@@ -1663,7 +1742,7 @@ Body:
NoClearance: true
NoSave: true
NoRemoveOnDead: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
- Status: Closeconfine2
Icon: EFST_RG_CCONFINE_S
DurationLookup: RG_CLOSECONFINE
@@ -1676,7 +1755,7 @@ Body:
NoClearance: true
NoSave: true
NoRemoveOnDead: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
Fail:
Closeconfine2: true
- Status: Dancing
@@ -1693,10 +1772,9 @@ Body:
NoDispell: true
NoBanishingBuster: true
NoClearance: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
RequireWeapon: true
OverlapIgnoreLevel: true
NoSave: true
EndOnEnd:
Longing: true
- Status: Elementalchange
@@ -1860,8 +1938,9 @@ Body:
StopWalking: true
NoSave: true
NoClearance: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
Debuff: true
RemoveOnHermode: true
- Status: Spurt
Icon: EFST_STRUP
DurationLookup: TK_RUN
@@ -1871,6 +1950,7 @@ Body:
NoSave: true
NoClearance: true
RequireWeapon: true
RemoveOnHermode: true
- Status: Spirit
Icon: EFST_SOULLINK
DurationLookup: SL_HIGH
@@ -1882,6 +1962,7 @@ Body:
NoClearance: true
NoSave: true
NoBanishingBuster: true
RemoveOnHermode: true
- Status: Coma
DurationLookup: NPC_DARKBLESSING
Flags:
@@ -2176,8 +2257,8 @@ Body:
NoDispell: true
NoBanishingBuster: true
NoClearance: true
RemoveOnChangeMap: true
RemoveOnMapWarp: true
NoSave: true
- Status: Sun_Comfort
Icon: EFST_SUN_COMFORT
DurationLookup: SG_SUN_COMFORT
@@ -2185,7 +2266,6 @@ Body:
Def2: true
Flags:
RemoveOnMapWarp: true
NoSave: true
- Status: Moon_Comfort
Icon: EFST_MOON_COMFORT
DurationLookup: SG_MOON_COMFORT
@@ -2193,7 +2273,6 @@ Body:
Flee: true
Flags:
RemoveOnMapWarp: true
NoSave: true
- Status: Star_Comfort
Icon: EFST_STAR_COMFORT
DurationLookup: SG_STAR_COMFORT
@@ -2201,7 +2280,6 @@ Body:
Aspd: true
Flags:
RemoveOnMapWarp: true
NoSave: true
- Status: Fusion
DurationLookup: SG_FUSION
CalcFlags:
@@ -2232,6 +2310,7 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnHermode: true
EndOnStart:
Assumptio: true
- Status: Swoo
@@ -2331,6 +2410,7 @@ Body:
NoClearance: true
NoBanishingBuster: true
NoDispell: true
RemoveOnHermode: true
- Status: Bunsinjyutsu
Icon: EFST_NJ_BUNSINJYUTSU
DurationLookup: NJ_BUNSINJYUTSU
@@ -2341,6 +2421,7 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnHermode: true
- Status: Kaensin
Flags:
NoWarning: true
@@ -2397,8 +2478,7 @@ Body:
Vit: true
Int: true
Flags:
RemoveOnMapWarp: true
NoSave: true
RemoveOnChangeMap: true
Fail:
Change: true
- Status: Bloodlust
@@ -2456,6 +2536,7 @@ Body:
SendVal1: true
OverlapIgnoreLevel: true
RemoveOnUnequipWeapon: true
RemoveOnHermode: true
EndOnStart:
Enchantarms: true
Aspersio: true
@@ -3209,7 +3290,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
NoSave: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
- Status: Bite
Icon: EFST_WUGBITE
DurationLookup: RA_WUGBITE
@@ -3241,7 +3322,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
NoSave: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
- Status: Acceleration
Icon: EFST_ACCELERATION
DurationLookup: NC_ACCELERATION
@@ -3323,7 +3404,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
NoSave: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
- Status: Stealthfield
Icon: EFST_STEALTHFIELD
DurationLookup: NC_STEALTHFIELD
@@ -3346,7 +3427,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
NoSave: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
- Status: Overheat
Icon: EFST_OVERHEAT
Flags:
@@ -3755,7 +3836,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
NoSave: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
Debuff: true
Fail:
Hallucinationwalk: true
@@ -4142,7 +4223,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
StopAttacking: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
- Status: Cursedcircle_Target
Icon: EFST_CURSEDCIRCLE_TARGET
DurationLookup: SR_CURSEDCIRCLE
@@ -4484,7 +4565,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
NoSave: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
- Status: _Bodypaint
Icon: EFST_BODYPAINT
DurationLookup: SC_BODYPAINT
@@ -4618,8 +4699,7 @@ Body:
NoDispell: true
NoBanishingBuster: true
NoClearance: true
RemoveOnMapWarp: true
NoSave: true
RemoveOnChangeMap: true
- Status: _Bloodylust
Icon: EFST_BLOODYLUST
DurationLookup: SC_BLOODYLUST
@@ -5213,7 +5293,7 @@ Body:
Flags:
StopWalking: true
NoSave: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
- Status: Tinder_Breaker2
Icon: EFST_TINDER_BREAKER
DurationLookup: MH_TINDER_BREAKER
@@ -5224,7 +5304,7 @@ Body:
Flags:
StopWalking: true
NoSave: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
- Status: Cbc
Icon: EFST_CBC
DurationLookup: MH_CBC
@@ -5758,9 +5838,10 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
NoBanishingBuster: true
NoDispell: true
RemoveOnHermode: true
- Status: Mtf_Aspd2
Icon: EFST_MTF_ASPD2
CalcFlags:
@@ -6063,6 +6144,7 @@ Body:
Flags:
StopAttacking: true
RemoveOnDamaged: true
RemoveOnChangeMap: true
RemoveOnMapWarp: true
- Status: Su_Stoop
Icon: EFST_SU_STOOP
@@ -6364,6 +6446,7 @@ Body:
Flags:
NoRemoveOnDead: true
NoClearbuff: true
RemoveOnHermode: true
- Status: Geffen_Magic2
Icon: EFST_GEFFEN_MAGIC2
CalcFlags:
@@ -6628,8 +6711,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
NoClearbuff: true
RemoveOnMapWarp: true
NoSave: true
RemoveOnChangeMap: true
- Status: Entry_Queue_Apply_Delay
Icon: EFST_ENTRY_QUEUE_APPLY_DELAY
Flags:
@@ -6701,7 +6783,7 @@ Body:
Icon: EFST_FLASHKICK
DurationLookup: SJ_FLASHKICK
Flags:
RemoveOnMapWarp: true
RemoveOnChangeMap: true
NoBanishingBuster: true
NoDispell: true
NoClearance: true
@@ -6718,7 +6800,7 @@ Body:
NoClearance: true
StopAttacking: true
RemoveOnDamaged: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
Fail:
Bite: true
- Status: Starstance

View File

@@ -26,51 +26,384 @@
# Map Map name to be considered as the castle map.
# Name Name of the castle (used by scripts and guardian name tags).
# Npc NPC unique name to invoke ::OnGuildBreak on, when a occupied castle is abandoned during guild break.
# Type The WoE type this castle belongs to. (Default: First_Edition)
# ClientId Client side ID of the castle. (Default: 0)
# WarpEnabled If the warp to the castle is enabled. (Default: false)
# WarpX X coordinate to warp to. (Default: 0)
# WarpY Y coordinate to warp to. (Default: 0)
# WarpCost Zeny cost to use the warp. (Default: 100)
# WarpCostSiege Zeny cost to use the warp during WoE. (Default: 100000)
###########################################################################
Header:
Type: CASTLE_DB
Version: 1
Version: 2
Body:
# WOE FE castle
- Id: 0
Map: aldeg_cas01
Name: Neuschwanstein
#Name: Noisyubantian
Npc: Agit#aldeg_cas01
Type: First_Edition
ClientId: 6
WarpEnabled: true
WarpX: 212
WarpY: 175
- Id: 1
Map: aldeg_cas02
Name: Hohenschwangau
#Name: Hohensyubangawoo
Npc: Agit#aldeg_cas02
Type: First_Edition
ClientId: 7
WarpEnabled: true
WarpX: 82
WarpY: 71
- Id: 2
Map: aldeg_cas03
Name: Nuernberg
#Name: Nyirenverk
Npc: Agit#aldeg_cas03
Type: First_Edition
ClientId: 8
WarpEnabled: true
WarpX: 109
WarpY: 112
- Id: 3
Map: aldeg_cas04
Name: Wuerzburg
#Name: Byirtsburi
Npc: Agit#aldeg_cas04
Type: First_Edition
ClientId: 9
WarpEnabled: true
WarpX: 60
WarpY: 116
- Id: 4
Map: aldeg_cas05
Name: Rothenburg
#Name: Rotenburk
Npc: Agit#aldeg_cas05
Type: First_Edition
ClientId: 10
WarpEnabled: true
WarpX: 61
WarpY: 185
- Id: 5
Map: gefg_cas01
Name: Repherion
#Name: Reprion
Npc: Agit#gefg_cas01
Type: First_Edition
ClientId: 11
WarpEnabled: true
WarpX: 40
WarpY: 43
- Id: 6
Map: gefg_cas02
Name: Eeyolbriggar
#Name: Yolbriger
Npc: Agit#gefg_cas02
Type: First_Edition
ClientId: 12
WarpEnabled: true
WarpX: 22
WarpY: 66
- Id: 7
Map: gefg_cas03
Name: Yesnelph
#Name: Isinlife
Npc: Agit#gefg_cas03
Type: First_Edition
ClientId: 13
WarpEnabled: true
WarpX: 112
WarpY: 23
- Id: 8
Map: gefg_cas04
Name: Bergel
#Name: Berigel
Npc: Agit#gefg_cas04
Type: First_Edition
ClientId: 14
WarpEnabled: true
WarpX: 58
WarpY: 46
- Id: 9
Map: gefg_cas05
Name: Mersetzdeitz
#Name: Melsedetsu
Npc: Agit#gefg_cas05
Type: First_Edition
ClientId: 15
WarpEnabled: true
WarpX: 66
WarpY: 48
- Id: 10
Map: payg_cas01
Name: Bright Arbor
#Name: Mingting
Npc: Agit#payg_cas01
Type: First_Edition
ClientId: 16
WarpEnabled: true
WarpX: 115
WarpY: 57
- Id: 11
Map: payg_cas02
Name: Scarlet Palace
#Name: Tiantan
Npc: Agit#payg_cas02
Type: First_Edition
ClientId: 17
WarpEnabled: true
WarpX: 26
WarpY: 265
- Id: 12
Map: payg_cas03
Name: Holy Shadow
#Name: Fuying
Npc: Agit#payg_cas03
Type: First_Edition
ClientId: 18
WarpEnabled: true
WarpX: 43
WarpY: 264
- Id: 13
Map: payg_cas04
Name: Sacred Altar
#Name: Honglou
Npc: Agit#payg_cas04
Type: First_Edition
ClientId: 19
WarpEnabled: true
WarpX: 36
WarpY: 272
- Id: 14
Map: payg_cas05
Name: Bamboo Grove Hill
#Name: Zhulinxian
Npc: Agit#payg_cas05
Type: First_Edition
ClientId: 20
WarpEnabled: true
WarpX: 274
WarpY: 246
- Id: 15
Map: prtg_cas01
Name: Kriemhild
#Name: Creamhilt
Npc: Agit#prtg_cas01
Type: First_Edition
ClientId: 1
WarpEnabled: true
WarpX: 107
WarpY: 180
- Id: 16
Map: prtg_cas02
Name: Swanhild
#Name: Sbanhealt
Npc: Agit#prtg_cas02
Type: First_Edition
ClientId: 2
WarpEnabled: true
WarpX: 94
WarpY: 56
- Id: 17
Map: prtg_cas03
Name: Fadhgridh
#Name: Lazrigees
Npc: Agit#prtg_cas03
Type: First_Edition
ClientId: 3
WarpEnabled: true
WarpX: 46
WarpY: 97
- Id: 18
Map: prtg_cas04
Name: Skoegul
#Name: Squagul
Npc: Agit#prtg_cas04
Type: First_Edition
ClientId: 4
WarpEnabled: true
WarpX: 260
WarpY: 262
- Id: 19
Map: prtg_cas05
Name: Gondul
#Name: Guindull
Npc: Agit#prtg_cas05
Type: First_Edition
ClientId: 5
WarpEnabled: true
WarpX: 26
WarpY: 38
# WOE NGuild castle
- Id: 20
Map: nguild_alde
Name: Earth
Npc: Agit_N01
Type: First_Edition
- Id: 21
Map: nguild_gef
Name: Air
Npc: Agit_N02
Type: First_Edition
- Id: 22
Map: nguild_pay
Name: Water
Npc: Agit_N03
Type: First_Edition
- Id: 23
Map: nguild_prt
Name: Fire
Npc: Agit_N04
Type: First_Edition
# WOE SE castle
- Id: 24
Map: schg_cas01
Name: Himinn
Npc: Manager#schg_cas01
Type: Second_Edition
ClientId: 26
WarpEnabled: true
WarpX: 233
WarpY: 300
- Id: 25
Map: schg_cas02
Name: Andlangr
Npc: Manager#schg_cas02
Type: Second_Edition
ClientId: 27
WarpEnabled: true
WarpX: 101
WarpY: 372
- Id: 26
Map: schg_cas03
Name: Viblainn
Npc: Manager#schg_cas03
Type: Second_Edition
ClientId: 28
WarpEnabled: true
WarpX: 81
WarpY: 94
- Id: 27
Map: schg_cas04
Name: Hljod
Npc: Manager#schg_cas04
Type: Second_Edition
ClientId: 29
WarpEnabled: true
WarpX: 233
WarpY: 300
- Id: 28
Map: schg_cas05
Name: Skidbladnir
Npc: Manager#schg_cas05
Type: Second_Edition
ClientId: 30
WarpEnabled: true
WarpX: 233
WarpY: 300
- Id: 29
Map: arug_cas01
Name: Mardol
Npc: Manager#arug_cas01
Type: Second_Edition
ClientId: 21
WarpEnabled: true
WarpX: 77
WarpY: 371
- Id: 30
Map: arug_cas02
Name: Cyr
Npc: Manager#arug_cas02
Type: Second_Edition
ClientId: 22
WarpEnabled: true
WarpX: 301
WarpY: 332
- Id: 31
Map: arug_cas03
Name: Horn
Npc: Manager#arug_cas03
Type: Second_Edition
ClientId: 23
WarpEnabled: true
WarpX: 322
WarpY: 91
- Id: 32
Map: arug_cas04
Name: Gefn
Npc: Manager#arug_cas04
Type: Second_Edition
ClientId: 24
WarpEnabled: true
WarpX: 322
WarpY: 91
- Id: 33
Map: arug_cas05
Name: Bandis
Npc: Manager#arug_cas05
Type: Second_Edition
ClientId: 25
WarpEnabled: true
WarpX: 322
WarpY: 91
# WOE TE castle
- Id: 34
Map: te_aldecas1
Name: Kafragarten 1
Npc: Manager_TE#Glaris
Type: Third_Edition
- Id: 35
Map: te_aldecas2
Name: Kafragarten 2
Npc: Manager_TE#Defolty
Type: Third_Edition
- Id: 36
Map: te_aldecas3
Name: Kafragarten 3
Npc: Manager_TE#Sorin
Type: Third_Edition
- Id: 37
Map: te_aldecas4
Name: Kafragarten 4
Npc: Manager_TE#Bennit
Type: Third_Edition
- Id: 38
Map: te_aldecas5
Name: Kafragarten 5
Npc: Manager_TE#W
Type: Third_Edition
- Id: 39
Map: te_prtcas01
Name: Gloria 1
Npc: Manager_TE#Gaebolg
Type: Third_Edition
- Id: 40
Map: te_prtcas02
Name: Gloria 2
Npc: Manager_TE#Richard
Type: Third_Edition
- Id: 41
Map: te_prtcas03
Name: Gloria 3
Npc: Manager_TE#Wigner
Type: Third_Edition
- Id: 42
Map: te_prtcas04
Name: Gloria 4
Npc: Manager_TE#Heine
Type: Third_Edition
- Id: 43
Map: te_prtcas05
Name: Gloria 5
Npc: Manager_TE#Nerious
Type: Third_Edition

View File

@@ -1,19 +0,0 @@
// Cash Shop Database
// Contains the items sold in the ingame cash shop.
//
// Structure of Database:
// Type,ItemID,Price
//
// Type:
// 0: New
// 1: Hot
// 2: Limited
// 3: Rental
// 4: Gear
// 5: Buff
// 6: Heal
// 7: Other
// 8: Sale
//
// Price:
// Item cost, in cash points (#CASHPOINTS).

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -25723,7 +25723,7 @@ Body:
Rate: 140
- Item: C_Pig_Nose
Rate: 140
- Item: C_Cat_Ears_Hat
- Item: C_Cat_Ear_Hat
Rate: 140
- Item: C_Valkyrie_Circlet
Rate: 140
@@ -25996,7 +25996,7 @@ Body:
Rate: 140
- Item: C_Poring_On_Shoulder
Rate: 140
- Item: Costume_Yawata_Seal
- Item: C_FortunetellinSealed
Rate: 140
- Item: C_Pretty_Bear_WH
Rate: 140
@@ -26008,7 +26008,7 @@ Body:
Rate: 140
- Item: C_Dark_Snake_Lord_Stall
Rate: 140
- Item: Costume_Twin_Cannon
- Item: C_Twin_Canon
Rate: 140
- Item: C_Picnic_Basket
Rate: 140
@@ -26070,13 +26070,13 @@ Body:
Rate: 140
- Item: C_LittleGarden
Rate: 140
- Item: Costume_Twinkling_Red_Eyes
- Item: C_Blinking_Eyes_RD
Rate: 140
- Item: C_Blink_Eyes_Sakura
Rate: 140
- Item: Costume_Angola_Intention
- Item: C_Angola_Intention
Rate: 140
- Item: C_Stole_Of_Dominion
- Item: C_Stall_Of_Dominions
Rate: 140
- Item: C_Flowery_Vision_TH
Rate: 140
@@ -26100,7 +26100,7 @@ Body:
Rate: 130
- Item: C_Blessings_Of_Soul
Rate: 130
- Item: C_Crow
- Item: C_Gossip_Raven
Rate: 130
- Item: C_Halloween_Hat
Rate: 130
@@ -26118,7 +26118,7 @@ Body:
Rate: 130
- Item: C_Gift_Of_Snow
Rate: 130
- Item: C_Large_Ribbon_Muffler_Red
- Item: C_L_RibbonMuff_Red
Rate: 130
- Item: C_Imperial_Glory
Rate: 130
@@ -48211,3 +48211,788 @@ Body:
- Item: Trans_Scroll_Gazeti
- Item: Trans_Scroll_Kobold_Archer
- Item: Trans_Scroll_Necromancer
- Group: S_W_BREATH_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_W_Breath_Armor
- Item: S_W_Breath_Shield
- Item: S_W_Breath_Shoes
- Group: S_F_BREATH_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_F_Breath_Weapon
- Item: S_F_Breath_Pendant
- Item: S_F_Breath_Earing
- Group: S_SONIC_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Sonic_Armor
- Item: S_Sonic_Shield
- Item: S_Sonic_Shoes
- Group: S_STRAIN_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Strain_Weapon
- Item: S_Strain_Pendant
- Item: S_Strain_Earing
- Group: S_JACK_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Jack_Armor
- Item: S_Jack_Shield
- Item: S_Jack_Shoes
- Group: S_CHAIN_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Chain_Weapon
- Item: S_Chain_Pendant
- Item: S_Chain_Earing
- Group: S_CRIMSON_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Crimson_Armor
- Item: S_Crimson_Shield
- Item: S_Crimson_Shoes
- Group: S_VULCAN_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Vulcan_Armor
- Item: S_Vulcan_Shield
- Item: S_Vulcan_Shoes
- Group: S_BOOMERANG_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Boomerang_Weapon
- Item: S_Boomerang_Pendant
- Item: S_Boomerang_Earing
- Group: S_ARMS_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Arms_Weapon
- Item: S_Arms_Pendant
- Item: S_Arms_Earing
- Group: S_TORNADO_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Tornado_Armor
- Item: S_Tornado_Shield
- Item: S_Tornado_Shoes
- Group: S_DUPLELIGHT_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Duplelight_Armor
- Item: S_Duplelight_Shield
- Item: S_Duplelight_Shoes
- Group: S_MAGNUS_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Magnus_Weapon
- Item: S_Magnus_Pendant
- Item: S_Magnus_Earing
- Group: S_ADORAMUS_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Adoramus_Weapon
- Item: S_Adoramus_Pendant
- Item: S_Adoramus_Earing
- Group: S_JUDEX_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Judex_Armor
- Item: S_Judex_Shield
- Item: S_Judex_Shoes
- Group: S_ROLLING_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Rolling_Armor
- Item: S_Rolling_Shield
- Item: S_Rolling_Shoes
- Group: S_RIPPER_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Ripper_Weapon
- Item: S_Ripper_Pendant
- Item: S_Ripper_Earing
- Group: S_SLASH_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Slash_Armor
- Item: S_Slash_Shield
- Item: S_Slash_Shoes
- Group: S_KATAR_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Slash_Armor
- Item: S_Slash_Shield
- Item: S_Slash_Shoes
- Group: S_SHOOTING_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Shooting_Weapon
- Item: S_Shooting_Pendant
- Item: S_Shooting_Earing
- Group: S_ARROW_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Arrow_Armor
- Item: S_Arrow_Shield
- Item: S_Arrow_Shoes
- Group: S_AIMED_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Aimed_Weapon
- Item: S_Aimed_Pendant
- Item: S_Aimed_Earing
- Group: S_CLUSTER_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Aimed_Weapon
- Item: S_Aimed_Pendant
- Item: S_Aimed_Earing
- Group: S_BANISH_CANNON_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Banish_Cannon_Armor
- Item: S_Banish_Cannon_Shield
- Item: S_Banish_Cannon_Shoes
- Group: S_BRAND_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Brand_Armor
- Item: S_Brand_Shield
- Item: S_Brand_Shoes
- Group: S_GENESIS_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Genesis_Weapon
- Item: S_Genesis_Pendant
- Item: S_Genesis_Earing
- Group: S_CHAIN_PRESS_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Chain_Press_Weapon
- Item: S_Chain_Press_Pendant
- Item: S_Chain_Press_Earing
- Group: S_GRAVE_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Grave_Weapon
- Item: S_Grave_Pendant
- Item: S_Grave_Earing
- Group: S_DUST_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Dust_Armor
- Item: S_Dust_Shield
- Item: S_Dust_Shoes
- Group: S_VARETYR_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Varetyr_Weapon
- Item: S_Varetyr_Pendant
- Item: S_Varetyr_Earing
- Group: S_PSYCHIC_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Psychic_Armor
- Item: S_Psychic_Shield
- Item: S_Psychic_Shoes
- Group: S_SPORE_BOMB_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Spore_Bomb_Armor
- Item: S_Spore_Bomb_Shield
- Item: S_Spore_Bomb_Shoes
- Group: S_CANNON_CART_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Cannon_Cart_Weapon
- Item: S_Cannon_Cart_Pendant
- Item: S_Cannon_Cart_Earing
- Group: S_CRAZY_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Crazy_Weapon
- Item: S_Crazy_Pendant
- Item: S_Crazy_Earing
- Group: S_CART_TORNADO_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Cart_Tornado_Armor
- Item: S_Cart_Tornado_Shield
- Item: S_Cart_Tornado_Shoes
- Group: S_KNUCKLEARROW_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Knucklearrow_Armor
- Item: S_Knucklearrow_Shield
- Item: S_Knucklearrow_Shoes
- Group: S_SKYNETBLOW_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Skynetblow_Weapon
- Item: S_Skynetblow_Pendant
- Item: S_Skynetblow_Earing
- Group: S_RAMPAGE_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Rampage_Armor
- Item: S_Rampage_Shield
- Item: S_Rampage_Shoes
- Group: S_TIGERCANNON_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_TigerCannon_Weapon
- Item: S_Tigercannon_Pendant
- Item: S_Tigercannon_Earing
- Group: S_MENACE_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Menace_Armor
- Item: S_Menace_Shield
- Item: S_Menace_Shoes
- Group: S_SHADOWSPELL_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Shadowspell_Weapon
- Item: S_Shadowspell_Pendant
- Item: S_Shadowspell_Earing
- Group: S_TRIANGLE_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Triangle_Armor
- Item: S_Triangle_Shield
- Item: S_Triangle_Shoes
- Group: S_PAINT_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Paint_Weapon
- Item: S_Paint_Pendant
- Item: S_Paint_Earing
- Group: S_RAINSTORM_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Rainstorm_Armor
- Item: S_Rainstorm_Shield
- Item: S_Rainstorm_Shoes
- Group: S_METALIC_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Metalic_Armor
- Item: S_Metalic_Shield
- Item: S_Metalic_Shoes
- Group: S_ARROWVULCAN_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Arrowvulcan_Weapon
- Item: S_Arrowvulcan_Pendant
- Item: S_Arrowvulcan_Earing
- Group: S_REVERBERATION_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Reverberation_Weapon
- Item: S_Reverberation_Pendant
- Item: S_Reverberation_Earing
- Group: S_MOONLIGHT_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Moonlight_Earring
- Item: S_Moonlight_Pendant
- Item: S_Moonlight_Shoes
- Group: S_SUNSHINE_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Sunshine_Weapon
- Item: S_Sunshine_Shield
- Item: S_Sunshine_Armor
- Group: S_STARDUST_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Stardust_Weapon
- Item: S_Stardust_Shield
- Item: S_Stardust_Armor
- Group: S_S_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_S_Weapon
- Item: S_S_Shield
- Item: S_S_Armor
- Group: S_EVILCURSE_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Evilcurse_Earring
- Item: S_Evilcurse_Pendant
- Item: S_Evilcurse_Shoes
- Group: S_SYURIKEN_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Syuriken_Earing
- Item: S_Syuriken_Pendant
- Item: S_Syuriken_Shoes
- Group: S_KUNAI_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Kunai_Weapon
- Item: S_Kunai_Shield
- Item: S_Kunai_Armor
- Group: S_HUUSOUKA_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Huusouka_Earing
- Item: S_Huusouka_Pendant
- Item: S_Huusouka_Shoes
- Group: S_KAMAENRAKU_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Kamaenraku_Weapon
- Item: S_Kamaenraku_Shield
- Item: S_Kamaenraku_Armor
- Group: S_GOD_HAMMER_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_God_Hammer_Weapon
- Item: S_God_Hammer_Shield
- Item: S_God_Hammer_Armor
- Group: S_SHATTER_BUSTER_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Shatter_Buster_Earing
- Item: S_Shatter_B_Pendant
- Item: S_Shatter_Buster_Shoes
- Group: S_TAIL_DRAGON_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Tail_Dragon_Weapon
- Item: S_Tail_Dragon_Shield
- Item: S_Tail_Dragon_Armor
- Group: S_TRIP_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Trip_Weapon
- Item: S_Trip_Shield
- Item: S_Trip_Armor
- Group: S_FLARE_DANCE_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Flare_Dance_Earing
- Item: S_Flare_Dance_Pendant
- Item: S_Flare_Dance_Shoes
- Group: S_SUPER_MAGIC_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Super_Magic_Shield
- Item: S_Super_Magic_Armor
- Item: S_Super_Magic_Shoes
- Group: S_SUPER_POWER_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Super_Power_Weapon
- Item: S_Super_Power_Pendant
- Item: S_Super_Power_Earing
- Group: S_SILVERVINE_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Silvervine_Earing
- Item: S_Silvervine_Pendant
- Item: S_Silvervine_Shoes
- Group: S_CATNIP_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Catnip_Weapon
- Item: S_Catnip_Shield
- Item: S_Catnip_Armor
- Group: S_SAVAGERABBIT_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_SavageRabbit_Earing
- Item: S_SavageRabbit_Pendant
- Item: S_SavageRabbit_Shoes
- Group: S_PICKYRUSH_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Pickyrush_Weapon
- Item: S_Pickyrush_Shield
- Item: S_Pickyrush_Armor
- Group: S_RUNEKNIGHT_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Swordman_earring
- Item: S_Swordman_Pendant
- Item: S_Knight_Shoes
- Item: S_Knight_Armor
- Item: S_Runeknight_Weapon
- Item: S_Runeknight_Shield
- Group: S_ROYALGUARD_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Swordman_earring
- Item: S_Swordman_Pendant
- Item: S_Crusader_Shoes
- Item: S_Crusader_Armor
- Item: S_Royalguard_Weapon
- Item: S_Royalguard_Shield
- Group: S_WARLOCK_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Magician_earring
- Item: S_Magician_Pendant
- Item: S_Wizard_Shoes
- Item: S_Wizard_Armor
- Item: S_Warlock_Weapon
- Item: S_Warlock_Shield
- Group: S_SORCERER_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Magician_earring
- Item: S_Magician_Pendant
- Item: S_Sage_Shoes
- Item: S_Sage_Armor
- Item: S_Sorcerer_Weapon
- Item: S_Sorcerer_Shield
- Group: S_MECHANIC_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Merchant_earring
- Item: S_Merchant_Pendant
- Item: S_Blacksmith_Shoes
- Item: S_Blacksmith_Armor
- Item: S_Mechanic_weapon
- Item: S_Mechanic_Shield
- Group: S_GENERIC_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Merchant_earring
- Item: S_Merchant_Pendant
- Item: S_Alchemist_Shoes
- Item: S_Alchemist_Armor
- Item: S_Genetic_Weapon
- Item: S_Genetic_Shield
- Group: S_ARCHBISHOP_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Acolyte_earring
- Item: S_Acolyte_Pendant
- Item: S_Priest_Shoes
- Item: S_Priest_Armor
- Item: S_Archbishop_Weapon
- Item: S_Archbishop_Shield
- Group: S_SURA_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Acolyte_earring
- Item: S_Acolyte_Pendant
- Item: S_Monk_Shoes
- Item: S_Monk_Armor
- Item: S_Sura_weapon
- Item: S_Sura_Shield
- Group: S_GUILLOTINECROSS_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Thief_Pendant
- Item: S_Assassin_Shoes
- Item: S_Assassin_Armor
- Item: S_Guillotine_Weapon
- Item: S_Guillotine_Shield
- Item: S_Thief_earring
- Group: S_SHADOWCHASER_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Thief_Pendant
- Item: S_Rogue_Shoes
- Item: S_Rogue_Armor
- Item: S_Shadowchaser_Weapon
- Item: S_Shadowchaser_Shield
- Item: S_Thief_earring
- Group: S_RANGER_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Archer_Pendant
- Item: S_Hunter_Shoes
- Item: S_Hunter_Armor
- Item: S_Ranger_Weapon
- Item: S_Ranger_Shield
- Item: S_Archer_earring
- Group: S_WANDERER_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Archer_Pendant
- Item: S_Dancer_Shoes
- Item: S_Dancer_Armor
- Item: S_Wanderer_Weapon
- Item: S_Wanderer_Shield
- Item: S_Archer_earring
- Group: S_MINSTREL_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Archer_Pendant
- Item: S_Bard_Shoes
- Item: S_Bard_Armor
- Item: S_Minstrel_Weapon
- Item: S_Minstrel_Shield
- Item: S_Archer_earring
- Group: S_STAR_EMPEROR_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Taekwon_Weapon
- Item: S_Taekwon_Shield
- Item: S_Star_Emperor_Armor
- Item: S_Star_Emperor_Shoes
- Group: S_SOUL_REAPER_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Taekwon_Weapon
- Item: S_Taekwon_Shield
- Item: S_Soul_Reaper_Armor
- Item: S_Soul_Reaper_Shoes
- Group: S_KAGEROU_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Ninja_Weapon
- Item: S_Ninja_Shield
- Item: S_Kagerou_Armor
- Item: S_Kagerou_Shoes
- Group: S_OBORO_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Ninja_Weapon
- Item: S_Ninja_Shield
- Item: S_Oboro_Armor
- Item: S_Oboro_Shoes
- Group: S_REBELLION_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Gunslinger_Weapon
- Item: S_Gunslinger_Shield
- Item: S_Rebellion_Armor
- Item: S_Rebellion_Shoes
- Group: S_SUPERNOVICE_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_SuperNovice_Weapon
- Item: S_SuperNovice_Shield
- Group: S_DORAM_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_DoramMagical_Weapon
- Item: S_DoramPhysical_Weapon
- Item: S_DoramPhysical_Shield
- Item: S_DoramMagical_Shield
- Item: S_DoramPhysical_Armor
- Item: S_DoramPhysical_Shoes
- Item: S_DoramMagical_Armor
- Item: S_DoramMagical_Shoes
- Group: S_MAMMOTH_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Mammoth_Armor
- Item: S_Mammoth_Shoes
- Item: S_Mammoth_Pendant
- Item: S_Mammoth_Earring
- Item: S_Mammoth_Weapon
- Item: S_Mammoth_Shield
- Group: S_GEMSTONE_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Gemstone_Armor
- Item: S_Gemstone_Shoes
- Item: S_Gemstone_Shield
- Item: S_Gemstone_Weapon
- Item: S_Gemstone_Earring
- Item: S_Gemstone_Pendent
- Group: S_PENE1_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Penetration_Earring
- Item: S_Penetration_Pendent
- Item: S_Exe_Ho_Weapon
- Item: S_Fis_In_Weapon
- Item: S_Sci_Hu_Weapon
- Item: S_Viv_Dr_Weapon
- Item: S_Exo_Co_Weapon
- Group: S_PENE2_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Penetration_Shoes
- Item: S_Penetration_Shield
- Item: S_ExeHoly_Armor
- Item: S_ExoCorrupt_Armor
- Item: S_DragonVib_Armor
- Item: S_SciHunting_Armor
- Item: S_FishInsect_Armor
- Group: S_TEMP1_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Tempest_Earring
- Item: S_Tempest_Pendent
- Item: S_M_Exo_Co_Weapon
- Item: S_M_Viv_Dr_Weapon
- Item: S_M_Sci_Hu_Weapon
- Item: S_M_Fis_In_Weapon
- Item: S_M_Exe_Ho_Weapon
- Group: S_TEMP2_CUBE
SubGroups:
- SubGroup: 0
List:
- Item: S_Tempest_Shield
- Item: S_Tempest_Shoes
- Item: S_M_ExeHoly_Armor
- Item: S_M_ExoCorrupt_Armor
- Item: S_M_DragonVib_Armor
- Item: S_M_SciHunting_Armor
- Item: S_M_FishInsect_Armor
- Group: BLACKSMITH_BLESS_BOX_3
SubGroups:
- SubGroup: 0
List:
- Item: Blacksmith_Blessing
Amount: 3
- Group: SHADOW_HAMMER_BOX_3
SubGroups:
- SubGroup: 0
List:
- Item: Shadow_Refine_Hammer
Amount: 3
- Group: EDP
SubGroups:
- SubGroup: 0
List:
- Item: Poison_Bottle
- Item: Poison_Bottle_B
- Group: MF_NOTELEPORT
SubGroups:
- SubGroup: 0
List:
- Item: Wing_Of_Fly
- Item: Giant_Fly_Wing
- Item: N_Fly_Wing
- Item: E_Giant_Fly_Wing
- Item: F_Giant_Fly_Wing
- Item: C_Wing_Of_Fly
- Item: N_Fly_Wing_
- Item: Compressed_Wing_Of_Fly
- Item: Comp_Wing_Of_Fly
- Group: MF_NORETURN
SubGroups:
- SubGroup: 0
List:
- Item: Wing_Of_Butterfly
- Item: N_Butterfly_Wing
- Item: Dun_Tele_Scroll1
- Item: Dun_Tele_Scroll2
- Item: Dun_Tele_Scroll3
- Item: E_Dun_Tele_Scroll1
- Item: F_Dun_Tele_Scroll1
- Item: WOB_Rune
- Item: E_WOB_Rune
- Item: F_WOB_Rune
- Item: WOB_Schwaltz
- Item: E_WOB_Schwaltz
- Item: F_WOB_Schwaltz
- Item: WOB_Rachel
- Item: E_WOB_Rachel
- Item: F_WOB_Rachel
- Item: WOB_Local
- Item: E_WOB_Local
- Item: F_WOB_Local
- Item: Siege_Teleport_Scroll
- Item: Siege_Teleport_Scroll2
- Item: E_Siege_Teleport_Scroll
- Group: GIANT_FLY_WING
SubGroups:
- SubGroup: 0
List:
- Item: Giant_Fly_Wing
- Item: E_Giant_Fly_Wing
- Item: F_Giant_Fly_Wing

View File

@@ -6892,3 +6892,91 @@ Body:
# Amount: 150
# ResultItem: Blessed_Knife_LT
# ChangeRefine: 1
- Item: Dimmen_A_Reform
BaseItems:
- BaseItem: Under_Seal_D_Key
MaximumRefine: 0
CardsAllowed: false
Materials:
- Material: Dimmension_Jewel
Amount: 1
- Material: Dimmension_Jewelry
Amount: 1
- Material: Herosria_Jewel
Amount: 1
- Material: Creed_Of_Herosria
Amount: 1
ResultItem: Dimmension_W_Key
- BaseItem: Under_Seal_D_Padlock
MaximumRefine: 0
CardsAllowed: false
Materials:
- Material: Dimmension_Jewel
Amount: 1
- Material: Dimmension_Jewelry
Amount: 1
- Material: Herosria_Jewel
Amount: 1
- Material: Justice_Of_Herosria
Amount: 1
ResultItem: Dimmension_W_Padlock
- BaseItem: Under_Seal_D_keyring
MaximumRefine: 0
CardsAllowed: false
Materials:
- Material: Dimmension_Jewel
Amount: 1
- Material: Dimmension_Jewelry
Amount: 1
- Material: Herosria_Jewel
Amount: 1
- Material: Glory_Of_Herosria
Amount: 1
ResultItem: Dimmension_W_Keyring
- Item: Dimmen_A_Refine
BaseItems:
- BaseItem: Dimmension_W_Key
MinimumRefine: 9
MaximumRefine: 11
CardsAllowed: false
Materials:
- Material: Heros_Gold_Bar
Amount: 50
- Material: Heros_Silver_Bar
Amount: 100
- Material: Heros_Copper_Bar
Amount: 200
- Material: Heros_Iron_Bar
Amount: 300
ResultItem: Dimmension_W_Key
ChangeRefine: 1
- BaseItem: Dimmension_W_Padlock
MinimumRefine: 9
MaximumRefine: 11
CardsAllowed: false
Materials:
- Material: Heros_Gold_Bar
Amount: 50
- Material: Heros_Silver_Bar
Amount: 100
- Material: Heros_Copper_Bar
Amount: 200
- Material: Heros_Iron_Bar
Amount: 300
ResultItem: Dimmension_W_Padlock
ChangeRefine: 1
- BaseItem: Dimmension_W_Keyring
MinimumRefine: 9
MaximumRefine: 11
CardsAllowed: false
Materials:
- Material: Heros_Gold_Bar
Amount: 50
- Material: Heros_Silver_Bar
Amount: 100
- Material: Heros_Copper_Bar
Amount: 200
- Material: Heros_Iron_Bar
Amount: 300
ResultItem: Dimmension_W_Keyring
ChangeRefine: 1

View File

@@ -1387,7 +1387,7 @@ Body:
Amount: 10
- Item: Frozen_Stone_Fragment
Amount: 10
- Item: Spirit_Jewel
- Item: SpritJewel
Amount: 10
- Item: Snowball
Amount: 10
@@ -1419,7 +1419,7 @@ Body:
Amount: 10
- Item: Fine_Old_Doll
Amount: 10
- Item: Old_Shell
- Item: OldShell
Amount: 10
- Item: Ein_SOLIDDUST
Amount: 10
@@ -1602,7 +1602,7 @@ Body:
- Item: C_Charleston_Antenna
- Item: C_Wings_of_Uriel
- Item: C_Pig_Nose
- Item: C_Cat_Ears_Hat
- Item: C_Cat_Ear_Hat
- Item: C_Valkyrie_Circlet
- Item: C_Eremes_Scarf_Black
- Item: C_Eleanor_Wig
@@ -1738,13 +1738,13 @@ Body:
- Item: C_Big_Foxtail
- Item: C_T_Bear_Bag
- Item: C_Poring_On_Shoulder
- Item: Costume_Yawata_Seal
- Item: C_FortunetellinSealed
- Item: C_Pretty_Bear_WH
- Item: C_Bicolor_Cat_Witch_Hat
- Item: C_Nifl_Bloom
- Item: C_Floating_Ball_TW
- Item: C_Dark_Snake_Lord_Stall
- Item: Costume_Twin_Cannon
- Item: C_Twin_Canon
- Item: C_Picnic_Basket
- Item: C_Magic_Helm
- Item: C_ManyStars_TW
@@ -1773,13 +1773,13 @@ Body:
- Item: C_Disapear_Time_TW
- Item: C_Magic_Heir_TW
- Item: C_Blink_Eyes_Sakura
- Item: Costume_Angola_Intention
- Item: C_Stole_Of_Dominion
- Item: C_Angola_Intention
- Item: C_Stall_Of_Dominions
- Item: C_Flowery_Vision_TH
- Item: C_Frill_Collar
- Item: C_Rose_Gothic_Bonnet
- Item: C_LittleGarden
- Item: Costume_Twinkling_Red_Eyes
- Item: C_Blinking_Eyes_RD
- Item: C_P_Ulysses_Feather
- Item: C_DancingButterfly_TW
- Item: C_Blue_Pencil_In_Mouth
@@ -1790,7 +1790,7 @@ Body:
- Item: C_Frog_Hood
- Item: C_Lude_Hood
- Item: C_Blessings_Of_Soul
- Item: C_Crow
- Item: C_Gossip_Raven
- Item: C_Halloween_Hat
- Item: C_Blessed_Veil
- Item: C_Eyes_Of_Ifrit
@@ -1799,7 +1799,7 @@ Body:
- Item: C_Wildcat_Knit_Cap
- Item: C_Pink_Fur_Hat
- Item: C_Gift_Of_Snow
- Item: C_Large_Ribbon_Muffler_Red
- Item: C_L_RibbonMuff_Red
- Item: C_Imperial_Glory
- Item: C_Black_Shiba_Inu_Hat
- Item: C_Black_Glasses
@@ -3272,11 +3272,11 @@ Body:
# RewardGroup: ENCHANTSTONE_RECIPE_3M
# Requirements:
# - Item: C_Pretty_Bear_WH
# - Item: Costume_Yawata_Seal
# - Item: C_FortunetellinSealed
# - Item: C_Floating_Ball_TW
# - Item: C_Dark_Snake_Lord_Stall
# - Item: C_Bicolor_Cat_Witch_Hat
# - Item: Costume_Twin_Cannon
# - Item: C_Twin_Canon
# - Item: C_Picnic_Basket
# - Item: C_Magic_Helm
# - Item: C_Fawn_Ear
@@ -3291,7 +3291,7 @@ Body:
# - Item: C_Frill_Collar
# - Item: C_Rose_Gothic_Bonnet
# - Item: C_LittleGarden
# - Item: Costume_Twinkling_Red_Eyes
# - Item: C_Blinking_Eyes_RD
# - Item: Egirnion_Box
# RewardGroup: EGIRNION_BOX
# Requirements:
@@ -3700,11 +3700,11 @@ Body:
# - Item: S_AllMighty_Pendant
# - Item: S_Tempest_Shield
# - Item: S_Tempest_Shoes
# - Item: S_Magic_Executioner_Holy_Water_Armor
# - Item: S_Magic_Exorcist_Corrupted_Armor
# - Item: S_Magic_Vibration_Dragon_Killer_Armor
# - Item: S_Magic_Scissor_Hunting_Armor
# - Item: S_Magic_Fishing_Insect_Net_Armor
# - Item: S_M_ExeHoly_Armor
# - Item: S_M_ExoCorrupt_Armor
# - Item: S_M_DragonVib_Armor
# - Item: S_M_SciHunting_Armor
# - Item: S_M_FishInsect_Armor
# - Item: S_Plasterer's_Armor_II
# - Item: S_Insomniac_Shoes_II
# - Item: S_Peerless_Armor_II
@@ -3728,11 +3728,11 @@ Body:
# - Item: S_Mortal_Blow_Pendant
# - Item: S_Penetration_Shoes
# - Item: S_Penetration_Shield
# - Item: S_Executioner_Holy_Water_Armor
# - Item: S_Exorcist_Corrupted_Armor
# - Item: S_Vibration_Dragon_Killer_Armor
# - Item: S_Scissor_Hunting_Armor
# - Item: S_Fishing_Insect_Net_Armor
# - Item: S_ExeHoly_Armor
# - Item: S_ExoCorrupt_Armor
# - Item: S_DragonVib_Armor
# - Item: S_SciHunting_Armor
# - Item: S_FishInsect_Armor
# - Item: Sentimental_Weapone_S
# - Item: Sentimental_Earring_S
# - Item: Sentimental_Pendant_S

View File

@@ -60,7 +60,7 @@ Body:
# - Item: Ein_1HSWORD
# - Item: Ein_1HGUN
# - Item: Ein_1H_Foxtail
- Item: Metal_Smelting_Ticket
- Item: Metal_Rifine_Ticket
ResultRefine: 7
CardsAllowed: true
TargetItems:
@@ -74,7 +74,7 @@ Body:
- Item: Metal_Bow
- Item: Metal_Two_Hand_Sword
- Item: Metal_Revolver
- Item: Huuma_Metal_Shuriken
- Item: Metal_Huuma_Shuriken
- Item: Metal_Foxtail
# - Item: Ein_Ddbox2
# TargetItems:
@@ -2657,21 +2657,21 @@ Body:
TargetItems:
- Item: Boost_TH_Sword
- Item: Boost_Katar
- Item: Boost_Mace
- Item: Boost_Hall
- Item: Boost_Staff
- Item: Boost_Bow
- Item: Boost_Spear
- Item: Boost_Sword
- Item: Boost_Dagger
- Item: Boost_Spellbook
- Item: Boost_Spl_Book
- Item: Boost_Guitar
- Item: Boost_Knuckles
- Item: Boost_Knuckle
- Item: Boost_Whip
- Item: Boost_Nindo
- Item: Boost_Gatling
- Item: Boost_Axe
- Item: Boost_Book
- Item: Boost_Rod
- Item: Boost_Text
- Item: Boost_Soul_Rod
- Item: Boost_Foxtail
- Item: Metal_7_Ticket
ResultRefine: 7
@@ -2689,7 +2689,7 @@ Body:
- Item: Metal_Bow
- Item: Metal_Foxtail
- Item: Metal_Revolver
- Item: Huuma_Metal_Shuriken
- Item: Metal_Huuma_Shuriken
- Item: Noblesse_Rifine_Ticket
ResultRefine: 9
CardsAllowed: true

File diff suppressed because it is too large Load Diff

View File

@@ -13041,6 +13041,69 @@
20837,ABR_INFINITY@ABR_INFINITY_BUSTER,chase,8605,1,10000,500,5000,yes,target,always,0,,,,,,,
20837,ABR_INFINITY@ABR_INFINITY_BUSTER,attack,8605,1,10000,500,5000,yes,target,always,0,,,,,,,
// sp_rudus4
20929,GIANT_CAPUT@NPC_EMOTION,chase,197,1,1000,0,30000,yes,self,always,0,,,,,,19,
20929,GIANT_CAPUT@NPC_EMOTION,idle,197,1,8000,0,30000,yes,self,always,0,,,,,,44,
20929,GIANT_CAPUT@NPC_COMBOATTACK,attack,171,2,1000,500,15000,no,target,always,0,,,,,,,
20929,GIANT_CAPUT@LK_SPIRALPIERCE,chase,397,3,3000,500,30000,no,target,always,0,,,,,,,
20929,GIANT_CAPUT@NPC_DARKNESSATTACK,chase,190,3,5000,500,10000,no,target,always,0,,,,,,,
20929,GIANT_CAPUT@NPC_DARKNESSATTACK,attack,190,3,5000,500,10000,no,target,always,0,,,,,,,
20929,GIANT_CAPUT@NPC_HELMBRAKE,attack,345,5,3000,0,30000,yes,target,always,0,,,,,,,
20929,GIANT_CAPUT@NPC_PULSESTRIKE,attack,661,3,2000,1000,60000,no,self,always,0,,,,,,,
20929,GIANT_CAPUT@NPC_POWERUP,attack,349,3,5000,0,60000,yes,self,myhpltmaxrate,30,,,,,,,
20929,GIANT_CAPUT@NPC_POWERUP,chase,349,3,5000,0,60000,yes,self,myhpltmaxrate,30,,,,,,,
20930,DOLORIAN@AL_TELEPORT,chase,26,1,3000,0,300000,yes,self,mobnearbygt,23,,,,,,12,
20930,DOLORIAN@NPC_EMOTION,chase,197,1,500,0,30000,yes,self,always,0,,,,,,19,
20930,DOLORIAN@NPC_CRITICALWOUND,attack,673,1,2000,0,60000,yes,target,always,0,,,,,,,
20930,DOLORIAN@NPC_EMOTION,idle,197,1,2000,0,30000,yes,self,always,0,,,,,,44,
20930,DOLORIAN@NPC_BLOODDRAIN,chase,199,1,3000,0,30000,yes,target,always,0,,,,,,,
20930,DOLORIAN@NPC_STONESKIN,chase,675,3,3000,500,30000,no,self,myhpltmaxrate,30,,,,,,47,
20930,DOLORIAN@NPC_POISONATTACK,attack,188,3,2000,500,10000,no,target,always,0,,,,,,,
20931,PLAGARION@AL_TELEPORT,chase,26,1,3000,0,300000,yes,self,mobnearbygt,23,,,,,,12,
20931,PLAGARION@NPC_EMOTION,chase,197,1,500,0,30000,yes,self,always,0,,,,,,19,
20931,PLAGARION@NPC_EMOTION,idle,197,1,2000,0,30000,yes,self,always,0,,,,,,44,
20931,PLAGARION@NPC_CRITICALWOUND,attack,673,3,2000,0,60000,yes,target,always,0,,,,,,,
20931,PLAGARION@MG_FIREBALL,chase,17,3,3000,500,30000,no,target,always,0,,,,,,,
20931,PLAGARION@NPC_FIREATTACK,chase,186,2,2000,500,30000,no,target,always,0,,,,,,,
20931,PLAGARION@NPC_DARKSTRIKE,chase,340,5,3000,500,30000,no,target,always,0,,,,,,,
20932,DEADRE@AL_TELEPORT,chase,26,1,3000,0,300000,yes,self,mobnearbygt,23,,,,,,12,
20932,DEADRE@NPC_EMOTION,chase,197,1,500,0,30000,yes,self,always,0,,,,,,19,
20932,DEADRE@AL_HEAL,idle,28,9,7000,500,5000,no,friend,myhpltmaxrate,50,,,,,,3,
20932,DEADRE@NPC_EMOTION,idle,197,1,2000,0,30000,yes,self,always,0,,,,,,14,
20932,DEADRE@AL_HEAL,attack,28,9,3000,500,15000,no,friend,always,0,,,,,,3,
20932,DEADRE@NPC_DARKCROSS,attack,338,5,3000,500,15000,no,target,always,0,,,,,,,
20932,DEADRE@AL_HOLYLIGHT,chase,156,1,3000,300,15000,no,target,always,0,,,,,,,
20932,DEADRE@NPC_HOLYATTACK,chase,189,3,4000,500,15000,no,target,always,0,,,,,,,
20932,DEADRE@AL_HEAL,idle,28,9,10000,700,3000,no,friend,friendhpltmaxrate,50,,,,,,,
20933,VENEDI@NPC_EMOTION,chase,197,1,500,0,30000,yes,self,always,0,,,,,,19,
20933,VENEDI@NPC_EMOTION,idle,197,1,2000,0,30000,yes,self,always,0,,,,,,44,
20933,VENEDI@NPC_BLINDATTACK,chase,177,3,3000,500,30000,no,target,always,0,,,,,,,
20933,VENEDI@NPC_POISONATTACK,attack,188,5,1000,0,5000,yes,target,always,0,,,,,,,
20933,VENEDI@NPC_POISON_BUSTER,attack,742,1,2000,1500,30000,no,self,always,0,,,,,,,
20933,VENEDI@NPC_CLOUD_KILL,attack,739,3,2000,500,15000,no,target,always,0,,,,,,,
20934,R001_BESTIA@AL_TELEPORT,idle,26,1,10000,0,0,yes,self,rudeattacked,0,,,,,,,
20934,R001_BESTIA@WZ_METEOR,idle,83,9,10000,0,5000,no,target,longrangeattacked,0,,,,,,,
20934,R001_BESTIA@AL_PNEUMA,idle,25,1,10000,0,1000,no,self,longrangeattacked,0,,,,,,,
20934,R001_BESTIA@AL_HEAL,idle,28,11,10000,0,3000,no,friend,myhpltmaxrate,50,,,,,,,
20934,R001_BESTIA@AL_HEAL,idle,28,5,10000,0,3000,no,friend,myhpltmaxrate,99,,,,,,,
20934,R001_BESTIA@NPC_SUMMONSLAVE,idle,196,1,10000,1000,30000,no,self,slavele,1,,,,,,,
20934,R001_BESTIA@NPC_CALLSLAVE,idle,352,1,10000,0,30000,no,self,always,0,,,,,,,
20934,R001_BESTIA@NPC_FIREBREATH,chase,654,10,2000,500,5000,no,target,myhpltmaxrate,80,,,,,,,
// 20934,R001_BESTIA@NPC_EARTHQUAKE_K,chase,750,5,10000,500,20000,no,target,myhpltmaxrate,40,,,,,,,
20934,R001_BESTIA@NPC_EARTHQUAKE,chase,653,5,10000,500,20000,no,target,myhpltmaxrate,40,,,,,,,
20934,R001_BESTIA@NPC_CALLSLAVE,attack,352,1,10000,0,30000,no,self,always,0,,,,,,,
20934,R001_BESTIA@NPC_SUMMONSLAVE,attack,196,1,10000,700,10000,no,self,slavele,2,,,,,,,
20934,R001_BESTIA@ST_FULLSTRIP,attack,476,5,2000,0,5000,no,target,always,0,,,,,,,
20934,R001_BESTIA@NPC_CRITICALWOUND,attack,673,3,2000,0,30000,no,target,always,0,,,,,,,
20934,R001_BESTIA@NPC_FIREBREATH,attack,654,10,2000,500,5000,no,target,myhpltmaxrate,80,,,,,,,
20934,R001_BESTIA@WZ_METEOR,attack,83,11,2000,500,5000,no,target,myhpltmaxrate,90,,,,,,,
20934,R001_BESTIA@KN_TWOHANDQUICKEN,attack,60,9,10000,0,100000,no,self,myhpltmaxrate,30,,,,,,,
// 20934,R001_BESTIA@NPC_EARTHQUAKE_K,attack,750,5,10000,500,20000,no,target,myhpltmaxrate,40,,,,,,,
20934,R001_BESTIA@NPC_EARTHQUAKE,attack,653,5,10000,500,20000,no,target,myhpltmaxrate,40,,,,,,,
20934,R001_BESTIA@NPC_PULSESTRIKE,attack,661,5,10000,0,15000,no,self,myhpltmaxrate,60,,,,,,,
20934,R001_BESTIA@NPC_DRAGONFEAR,attack,659,5,10000,0,10000,no,self,always,0,,,,,,,
// 20934,R001_BESTIA@NPC_DAMAGE_HEAL,attack,753,1,3000,1500,40000,no,target,myhpltmaxrate,20,,,,,,,
// Training Ground outside Prontera
21064,S_DUMMY_100_SMALL@NPC_ALLHEAL,attack,687,1,10000,0,500,no,self,myhpltmaxrate,90,,,,,,,
21064,S_DUMMY_100_SMALL@NPC_ALLHEAL,idle,687,1,10000,0,500,no,self,myhpltmaxrate,90,,,,,,,

View File

@@ -10420,15 +10420,37 @@ Body:
- Id: 16439
Title: Award Garden-Waiting
TimeLimit: 4h
- Id: 16521
Title: 4th floor of Rudus, an organic field for waste specimens
- Id: 16522
Title: 4th floor of Rudus, an organic field for waste specimens
- Id: 16523
Title: The solitude of the abyss
Title: Abyssal Solitude - Standby
TimeLimit: 4h
- Id: 16524
Title: Abyssal Solitude
Targets:
- Mob: DEADRE
Count: 10
- Mob: DOLORIAN
Count: 10
- Mob: PLAGARION
Count: 10
- Id: 16525
Title: Transformation and development - Standby
Title: Transformation and Evolution - Standby
TimeLimit: 4h
- Id: 16526
Title: Transformation and Evolution
Targets:
- Mob: GIANT_CAPUT
Count: 15
- Mob: VENEDI
Count: 15
- Id: 16527
Title: Data backup - Waiting
TimeLimit: 4h
- Id: 16528
Title: Data Backup
- Id: 16530
Title: The ground and fire
TimeLimit: 4h
@@ -10444,6 +10466,8 @@ Body:
- Id: 16538
Title: Natural change - Waiting
TimeLimit: 4h
- Id: 16540
Title: Data Backup
- Id: 16546
Title: Farm Worker
- Id: 16547

View File

@@ -10516,9 +10516,6 @@ Body:
Amount: 90
- Level: 5
Amount: 100
ItemCost:
- Item: Poison_Bottle
Amount: 1
Status: Edp
- Id: 379
Name: ASC_BREAKER

View File

@@ -254,6 +254,7 @@ Body:
NoSave: true
NoClearance: true
SpreadEffect: true
RemoveOnHermode: true
Fail:
Refresh: true
Inspiration: true
@@ -282,6 +283,7 @@ Body:
BossResist: true
Debuff: true
NoSaveInfinite: true
RemoveOnHermode: true
EndOnStart:
Freeze: true
Stone: true
@@ -307,6 +309,7 @@ Body:
Quicken: true
Flags:
RequireWeapon: true
RemoveOnHermode: true
Fail:
Decreaseagi: true
- Status: Concentrate
@@ -317,6 +320,7 @@ Body:
Dex: true
Flags:
FailedMado: true
RemoveOnHermode: true
Fail:
Quagmire: true
- Status: Hiding
@@ -335,11 +339,10 @@ Body:
OnTouch: true
StopAttacking: true
RemoveOnDamaged: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
NoBanishingBuster: true
NoDispell: true
NoClearance: true
NoSave: true
EndOnStart:
Closeconfine: true
Closeconfine2: true
@@ -368,6 +371,7 @@ Body:
Atk_Ele: true
Flags:
RemoveOnUnequipWeapon: true
RemoveOnHermode: true
EndOnStart:
Aspersio: true
Fireweapon: true
@@ -379,6 +383,8 @@ Body:
- Status: Poisonreact
Icon: EFST_POISONREACT
DurationLookup: AS_POISONREACT
Flags:
RemoveOnHermode: true
- Status: Quagmire
Icon: EFST_QUAGMIRE
DurationLookup: WZ_QUAGMIRE
@@ -391,6 +397,7 @@ Body:
NoSave: true
NoClearance: true
Debuff: true
RemoveOnHermode: true
Fail:
Speedup1: true
EndOnStart:
@@ -419,6 +426,7 @@ Body:
Angelus: true
Flags:
SendOption: true
RemoveOnHermode: true
- Status: Blessing
Icon: EFST_BLESSING
DurationLookup: AL_BLESSING
@@ -430,6 +438,7 @@ Body:
Flags:
BossResist: true
TaekwonAngel: true
RemoveOnHermode: true
- Status: Signumcrucis
Icon: EFST_CRUCIS
DurationLookup: AL_CRUCIS
@@ -450,6 +459,7 @@ Body:
Flags:
FailedMado: true
TaekwonAngel: true
RemoveOnHermode: true
Fail:
Quagmire: true
EndOnStart:
@@ -465,6 +475,7 @@ Body:
BossResist: true
NoSave: true
Debuff: true
RemoveOnHermode: true
Fail:
Speedup1: true
EndOnStart:
@@ -483,6 +494,7 @@ Body:
DurationLookup: PR_SLOWPOISON
Flags:
NoClearance: true
RemoveOnHermode: true
- Status: Impositio
Icon: EFST_IMPOSITIO
DurationLookup: PR_IMPOSITIO
@@ -491,6 +503,7 @@ Body:
Matk: true
Flags:
SuperNoviceAngel: true
RemoveOnHermode: true
EndOnStart:
Impositio: true
- Status: Suffragium
@@ -498,6 +511,7 @@ Body:
DurationLookup: PR_SUFFRAGIUM
Flags:
SuperNoviceAngel: true
RemoveOnHermode: true
- Status: Aspersio
Icon: EFST_ASPERSIO
DurationLookup: PR_ASPERSIO
@@ -505,6 +519,7 @@ Body:
Atk_Ele: true
Flags:
RemoveOnUnequipWeapon: true
RemoveOnHermode: true
EndOnStart:
Encpoison: true
Fireweapon: true
@@ -523,11 +538,13 @@ Body:
NoSave: true
NoClearance: true
#RemoveOnUnequipArmor: true
RemoveOnHermode: true
- Status: Kyrie
Icon: EFST_KYRIE
DurationLookup: PR_KYRIE
Flags:
SuperNoviceAngel: true
RemoveOnHermode: true
- Status: Magnificat
Icon: EFST_MAGNIFICAT
DurationLookup: PR_MAGNIFICAT
@@ -537,6 +554,7 @@ Body:
FailedMado: true
NoSave: true
SuperNoviceAngel: true
RemoveOnHermode: true
EndOnStart:
Offertorium: true
- Status: Gloria
@@ -546,11 +564,13 @@ Body:
Luk: true
Flags:
SuperNoviceAngel: true
RemoveOnHermode: true
- Status: Aeterna
Icon: EFST_LEXAETERNA
DurationLookup: PR_LEXAETERNA
Flags:
NoSave: true
RemoveOnHermode: true
Fail:
Stone: true
Freeze: true
@@ -563,6 +583,7 @@ Body:
Flags:
MadoCancel: true
RequireWeapon: true
RemoveOnHermode: true
Fail:
Quagmire: true
Decreaseagi: true
@@ -571,6 +592,7 @@ Body:
DurationLookup: BS_WEAPONPERFECT
Flags:
MadoCancel: true
RemoveOnHermode: true
- Status: Overthrust
Icon: EFST_OVERTHRUST
DurationLookup: BS_OVERTHRUST
@@ -578,6 +600,7 @@ Body:
OverThrust: true
Flags:
MadoCancel: true
RemoveOnHermode: true
Fail:
Maxoverthrust: true
- Status: Maximizepower
@@ -587,6 +610,7 @@ Body:
Regen: true
Flags:
MadoCancel: true
RemoveOnHermode: true
- Status: Trickdead
Icon: EFST_TRICKDEAD
DurationLookup: NV_TRICKDEAD
@@ -605,7 +629,8 @@ Body:
RemoveOnDamaged: true
NoSave: true
NoClearance: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
RemoveOnHermode: true
EndOnStart:
Dancing: true
- Status: Loud
@@ -613,6 +638,7 @@ Body:
DurationLookup: MC_LOUD
Flags:
MadoCancel: true
RemoveOnHermode: true
CalcFlags:
Str: true
Batk: true
@@ -621,6 +647,8 @@ Body:
DurationLookup: MG_ENERGYCOAT
Opt3:
EnergyCoat: true
Flags:
RemoveOnHermode: true
- Status: Brokenarmor
Icon: EFST_BROKENARMOR
DurationLookup: NPC_ARMORBRAKE
@@ -673,12 +701,14 @@ Body:
Flags:
NoClearance: true
OverlapIgnoreLevel: true
RemoveOnHermode: true
- Status: Aspdpotion2
Icon: EFST_ATTHASTE_POTION3
CalcFlags:
Aspd: true
Flags:
OverlapIgnoreLevel: true
RemoveOnHermode: true
- Status: Aspdpotion3
Icon: EFST_ATTHASTE_INFINITY
CalcFlags:
@@ -686,6 +716,7 @@ Body:
Flags:
NoClearance: true
OverlapIgnoreLevel: true
RemoveOnHermode: true
- Status: Speedup0
Icon: EFST_MOVHASTE_HORSE
CalcFlags:
@@ -703,6 +734,7 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnHermode: true
- Status: Atkpotion
Icon: EFST_PLUSATTACKPOWER
CalcFlags:
@@ -711,6 +743,7 @@ Body:
NoRemoveOnDead: true
NoClearance: true
OverlapIgnoreLevel: true
RemoveOnHermode: true
- Status: Matkpotion
Icon: EFST_PLUSMAGICPOWER
CalcFlags:
@@ -719,6 +752,7 @@ Body:
NoRemoveOnDead: true
NoClearance: true
OverlapIgnoreLevel: true
RemoveOnHermode: true
- Status: Wedding
States:
NoAttack: true
@@ -749,8 +783,7 @@ Body:
NoDispell: true
NoBanishingBuster: true
NoClearance: true
RemoveOnMapWarp: true
NoSave: true
RemoveOnChangeMap: true
MinDuration: 5000
- Status: Keeping
DurationLookup: NPC_KEEPING
@@ -762,6 +795,8 @@ Body:
CalcFlags:
Mdef: true
Def: true
Flags:
RemoveOnHermode: true
- Status: Stripweapon
Icon: EFST_NOEQUIPWEAPON
DurationLookup: RG_STRIPWEAPON
@@ -774,6 +809,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
NoSave: true
RemoveOnHermode: true
- Status: Stripshield
Icon: EFST_NOEQUIPSHIELD
DurationLookup: RG_STRIPSHIELD
@@ -786,6 +822,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
NoSave: true
RemoveOnHermode: true
- Status: Striparmor
Icon: EFST_NOEQUIPARMOR
DurationLookup: RG_STRIPARMOR
@@ -798,6 +835,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
NoSave: true
RemoveOnHermode: true
- Status: Striphelm
Icon: EFST_NOEQUIPHELM
DurationLookup: RG_STRIPHELM
@@ -810,6 +848,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
NoSave: true
RemoveOnHermode: true
- Status: Cp_Weapon
Icon: EFST_PROTECTWEAPON
DurationLookup: AM_CP_WEAPON
@@ -819,6 +858,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
RemoveChemicalProtect: true
RemoveOnHermode: true
- Status: Cp_Shield
Icon: EFST_PROTECTSHIELD
DurationLookup: AM_CP_SHIELD
@@ -828,6 +868,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
RemoveChemicalProtect: true
RemoveOnHermode: true
- Status: Cp_Armor
Icon: EFST_PROTECTARMOR
DurationLookup: AM_CP_ARMOR
@@ -837,6 +878,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
RemoveChemicalProtect: true
RemoveOnHermode: true
- Status: Cp_Helm
Icon: EFST_PROTECTHELM
DurationLookup: AM_CP_HELM
@@ -846,18 +888,21 @@ Body:
NoBanishingBuster: true
NoClearance: true
RemoveChemicalProtect: true
RemoveOnHermode: true
- Status: Autoguard
Icon: EFST_AUTOGUARD
DurationLookup: CR_AUTOGUARD
Flags:
NoClearance: true
RequireShield: true
RemoveOnHermode: true
- Status: Reflectshield
Icon: EFST_REFLECTSHIELD
DurationLookup: CR_REFLECTSHIELD
Flags:
NoClearance: true
RequireShield: true
RemoveOnHermode: true
EndOnStart:
Reflectdamage: true
- Status: Splasher
@@ -870,6 +915,7 @@ Body:
All: true
Flags:
NoSave: true
RemoveOnHermode: true
- Status: Defender
Icon: EFST_DEFENDER
DurationLookup: CR_DEFENDER
@@ -878,11 +924,13 @@ Body:
Aspd: true
Flags:
RequireShield: true
RemoveOnHermode: true
- Status: Magicrod
Icon: EFST_MAGICROD
DurationLookup: SA_MAGICROD
Flags:
NoSave: true
RemoveOnHermode: true
- Status: Spellbreaker
Flags:
NoWarning: true
@@ -916,6 +964,7 @@ Body:
Flags:
FailedMado: true
RequireWeapon: true
RemoveOnHermode: true
Fail:
Quagmire: true
- Status: Autocounter
@@ -970,6 +1019,7 @@ Body:
Debuff: true
NoClearance: true
NoSave: true
RemoveOnHermode: true
- Status: Combo
Flags:
NoClearbuff: true
@@ -982,8 +1032,7 @@ Body:
States:
NoMove: true
Flags:
RemoveOnMapWarp: true
NoSave: true
RemoveOnChangeMap: true
- Status: Bladestop
Icon: EFST_BLADESTOP
DurationLookup: MO_BLADESTOP
@@ -1000,7 +1049,8 @@ Body:
NoClearbuff: true
NoSave: true
NoClearance: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
RemoveOnHermode: true
- Status: Fireweapon
Icon: EFST_PROPERTYFIRE
DurationLookup: SA_FLAMELAUNCHER
@@ -1070,6 +1120,7 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnHermode: true
- Status: Deluge
Icon: EFST_GROUNDMAGIC
DurationLookup: SA_DELUGE
@@ -1129,6 +1180,7 @@ Body:
Flags:
NoSave: true
RequireWeapon: true
RemoveOnHermode: true
- Status: Parrying
Icon: EFST_PARRYING
DurationLookup: LK_PARRYING
@@ -1136,6 +1188,7 @@ Body:
NoSave: true
NoClearance: true
RequireWeapon: true
RemoveOnHermode: true
- Status: Concentration
Icon: EFST_LKCONCENTRATION
DurationLookup: LK_CONCENTRATION
@@ -1146,6 +1199,7 @@ Body:
Quicken: true
Flags:
NoSave: true
RemoveOnHermode: true
- Status: Tensionrelax
Icon: EFST_TENSIONRELAX
DurationLookup: LK_TENSIONRELAX
@@ -1154,6 +1208,7 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnHermode: true
- Status: Berserk
Icon: EFST_BERSERK
DurationLookup: LK_BERSERK
@@ -1194,6 +1249,7 @@ Body:
Aspd: true
Flags:
NoSave: true
RemoveOnHermode: true
- Status: Assumptio
Icon: EFST_ASSUMPTIO2
DurationLookup: HP_ASSUMPTIO
@@ -1203,6 +1259,8 @@ Body:
Assumptio: true
EndOnStart:
Kaite: true
Flags:
RemoveOnHermode: true
- Status: Basilica
Icon: EFST_BASILICA_BUFF
DurationLookup: HP_BASILICA
@@ -1213,6 +1271,7 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnHermode: true
- Status: Guildaura
Flags:
NoDispell: true
@@ -1225,6 +1284,7 @@ Body:
Matk: true
Flags:
NoSave: true
RemoveOnHermode: true
EndOnStart:
Magicpower: true
- Status: Edp
@@ -1251,6 +1311,7 @@ Body:
Flags:
FailedMado: true
NoSave: true
RemoveOnHermode: true
Fail:
Quagmire: true
- Status: Windwalk
@@ -1262,6 +1323,7 @@ Body:
Flags:
FailedMado: true
NoSave: true
RemoveOnHermode: true
Fail:
Quagmire: true
- Status: Meltdown
@@ -1304,7 +1366,7 @@ Body:
OnTouch: true
StopAttacking: true
RemoveOnDamaged: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
NoBanishingBuster: true
NoDispell: true
NoClearance: true
@@ -1324,8 +1386,7 @@ Body:
Opt3:
Marionette: true
Flags:
RemoveOnMapWarp: true
NoSave: true
RemoveOnChangeMap: true
Fail:
Marionette: true
- Status: Marionette2
@@ -1341,8 +1402,7 @@ Body:
Opt3:
Marionette: true
Flags:
RemoveOnMapWarp: true
NoSave: true
RemoveOnChangeMap: true
Fail:
Marionette2: true
- Status: Changeundead
@@ -1356,6 +1416,7 @@ Body:
Debuff: true
NoClearance: true
NoSave: true
RemoveOnHermode: true
EndOnStart:
Blessing: true
Increaseagi: true
@@ -1371,6 +1432,7 @@ Body:
NoSave: true
NoClearance: true
Debuff: true
RemoveOnHermode: true
- Status: Mindbreaker
Icon: EFST_MINDBREAKER
DurationLookup: PF_MINDBREAKER
@@ -1380,6 +1442,7 @@ Body:
Flags:
NoSave: true
Debuff: true
RemoveOnHermode: true
EndOnStart:
Freeze: true
Stone: true
@@ -1389,6 +1452,7 @@ Body:
DurationLookup: PF_MEMORIZE
Flags:
NoSave: true
RemoveOnHermode: true
- Status: Fogwall
Icon: EFST_FOGWALL
DurationLookup: PF_FOGWALL
@@ -1396,6 +1460,7 @@ Body:
BossResist: true
NoSave: true
NoClearance: true
RemoveOnHermode: true
- Status: Spiderweb
Icon: EFST_SPIDERWEB
DurationLookup: PF_SPIDERWEB
@@ -1416,8 +1481,9 @@ Body:
DurationLookup: CR_DEVOTION
Flags:
NoSave: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
OverlapIgnoreLevel: true
RemoveOnHermode: true
EndOnEnd:
Autoguard: true
Defender: true
@@ -1425,6 +1491,8 @@ Body:
Endure: true
- Status: Sacrifice
DurationLookup: PA_SACRIFICE
Flags:
RemoveOnHermode: true
- Status: Steelbody
Icon: EFST_STEELBODY
DurationLookup: MO_STEELBODY
@@ -1437,6 +1505,7 @@ Body:
Speed: true
Flags:
NoSave: true
RemoveOnHermode: true
Opt3:
SteelBody: true
- Status: Orcish
@@ -1500,7 +1569,8 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
RemoveOnHermode: true
- Status: Shadowweapon
Icon: EFST_PROPERTYDARK
DurationLookup: TK_SEVENWIND
@@ -1509,6 +1579,7 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnHermode: true
EndOnStart:
Encpoison: true
Aspersio: true
@@ -1526,6 +1597,7 @@ Body:
MadoCancel: true
NoSave: true
RequireWeapon: true
RemoveOnHermode: true
Fail:
Quagmire: true
Decreaseagi: true
@@ -1537,6 +1609,7 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnHermode: true
EndOnStart:
Encpoison: true
Aspersio: true
@@ -1554,6 +1627,7 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnHermode: true
EndOnStart:
Kaahi: true
- Status: Kaupe
@@ -1562,6 +1636,7 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnHermode: true
- Status: Onehand
Icon: EFST_ONEHANDQUICKEN
DurationLookup: KN_ONEHAND
@@ -1573,6 +1648,7 @@ Body:
NoSave: true
NoClearance: true
RequireWeapon: true
RemoveOnHermode: true
Fail:
Decreaseagi: true
EndOnStart:
@@ -1585,6 +1661,7 @@ Body:
DurationLookup: ST_PRESERVE
Flags:
NoSave: true
RemoveOnHermode: true
- Status: Battleorders
Icon: EFST_GDSKILL_BATTLEORDER
DurationLookup: GD_BATTLEORDER
@@ -1608,6 +1685,7 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnHermode: true
- Status: Maxoverthrust
Icon: EFST_OVERTHRUSTMAX
DurationLookup: WS_OVERTHRUSTMAX
@@ -1617,6 +1695,7 @@ Body:
MadoCancel: true
NoSave: true
RemoveOnUnequipWeapon: true
RemoveOnHermode: true
EndOnStart:
Overthrust: true
- Status: Hermode
@@ -1659,7 +1738,7 @@ Body:
NoClearance: true
NoSave: true
NoRemoveOnDead: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
- Status: Closeconfine2
Icon: EFST_RG_CCONFINE_S
DurationLookup: RG_CLOSECONFINE
@@ -1672,7 +1751,7 @@ Body:
NoClearance: true
NoSave: true
NoRemoveOnDead: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
Fail:
Closeconfine2: true
- Status: Dancing
@@ -1689,10 +1768,9 @@ Body:
NoDispell: true
NoBanishingBuster: true
NoClearance: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
RequireWeapon: true
OverlapIgnoreLevel: true
NoSave: true
EndOnEnd:
EnsembleFatigue: true
- Status: Elementalchange
@@ -1968,8 +2046,9 @@ Body:
StopWalking: true
NoSave: true
NoClearance: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
Debuff: true
RemoveOnHermode: true
- Status: Spurt
Icon: EFST_STRUP
DurationLookup: TK_RUN
@@ -1979,6 +2058,7 @@ Body:
NoSave: true
NoClearance: true
RequireWeapon: true
RemoveOnHermode: true
- Status: Spirit
Icon: EFST_SOULLINK
DurationLookup: SL_HIGH
@@ -1990,6 +2070,7 @@ Body:
NoClearance: true
NoSave: true
NoBanishingBuster: true
RemoveOnHermode: true
Fail:
Soulgolem: true
Soulshadow: true
@@ -2289,8 +2370,8 @@ Body:
NoDispell: true
NoBanishingBuster: true
NoClearance: true
RemoveOnChangeMap: true
RemoveOnMapWarp: true
NoSave: true
- Status: Sun_Comfort
Icon: EFST_SUN_COMFORT
DurationLookup: SG_SUN_COMFORT
@@ -2298,7 +2379,6 @@ Body:
Def2: true
Flags:
RemoveOnMapWarp: true
NoSave: true
- Status: Moon_Comfort
Icon: EFST_MOON_COMFORT
DurationLookup: SG_MOON_COMFORT
@@ -2306,7 +2386,6 @@ Body:
Flee: true
Flags:
RemoveOnMapWarp: true
NoSave: true
- Status: Star_Comfort
Icon: EFST_STAR_COMFORT
DurationLookup: SG_STAR_COMFORT
@@ -2314,7 +2393,6 @@ Body:
Aspd: true
Flags:
RemoveOnMapWarp: true
NoSave: true
- Status: Fusion
DurationLookup: SG_FUSION
CalcFlags:
@@ -2345,6 +2423,7 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnHermode: true
EndOnStart:
Assumptio: true
- Status: Swoo
@@ -2442,6 +2521,7 @@ Body:
NoClearance: true
NoBanishingBuster: true
NoDispell: true
RemoveOnHermode: true
- Status: Bunsinjyutsu
Icon: EFST_NJ_BUNSINJYUTSU
DurationLookup: NJ_BUNSINJYUTSU
@@ -2452,6 +2532,7 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnHermode: true
- Status: Kaensin
Flags:
NoWarning: true
@@ -2508,8 +2589,7 @@ Body:
Vit: true
Int: true
Flags:
RemoveOnMapWarp: true
NoSave: true
RemoveOnChangeMap: true
Fail:
Change: true
- Status: Bloodlust
@@ -2567,6 +2647,7 @@ Body:
SendVal1: true
OverlapIgnoreLevel: true
RemoveOnUnequipWeapon: true
RemoveOnHermode: true
EndOnStart:
Enchantarms: true
Aspersio: true
@@ -3332,7 +3413,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
NoSave: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
- Status: Bite
Icon: EFST_WUGBITE
DurationLookup: RA_WUGBITE
@@ -3364,7 +3445,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
NoSave: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
- Status: Acceleration
Icon: EFST_ACCELERATION
DurationLookup: NC_ACCELERATION
@@ -3451,7 +3532,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
NoSave: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
- Status: Stealthfield
Icon: EFST_STEALTHFIELD
DurationLookup: NC_STEALTHFIELD
@@ -3475,7 +3556,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
NoSave: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
- Status: Overheat
Icon: EFST_OVERHEAT
Flags:
@@ -3914,7 +3995,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
NoSave: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
Debuff: true
Fail:
Hallucinationwalk: true
@@ -4309,7 +4390,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
StopAttacking: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
SendVal3: true
- Status: Cursedcircle_Target
Icon: EFST_CURSEDCIRCLE_TARGET
@@ -4657,7 +4738,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
NoSave: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
SendVal3: true
- Status: _Bodypaint
Icon: EFST_BODYPAINT
@@ -4808,8 +4889,7 @@ Body:
NoDispell: true
NoBanishingBuster: true
NoClearance: true
RemoveOnMapWarp: true
NoSave: true
RemoveOnChangeMap: true
- Status: _Bloodylust
Icon: EFST_BLOODYLUST
DurationLookup: SC_BLOODYLUST
@@ -5482,7 +5562,7 @@ Body:
Flee: true
Flags:
NoSave: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
- Status: Tinder_Breaker2
Icon: EFST_TINDER_BREAKER
DurationLookup: MH_TINDER_BREAKER
@@ -5490,7 +5570,7 @@ Body:
Flee: true
Flags:
NoSave: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
Fail:
Tinder_Breaker2: true
- Status: Cbc
@@ -6030,9 +6110,10 @@ Body:
Flags:
NoSave: true
NoClearance: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
NoBanishingBuster: true
NoDispell: true
RemoveOnHermode: true
- Status: Extremityfist2
Icon: EFST_EXTREMITYFIST
DurationLookup: MO_EXTREMITYFIST
@@ -6369,6 +6450,7 @@ Body:
Flags:
StopAttacking: true
RemoveOnDamaged: true
RemoveOnChangeMap: true
RemoveOnMapWarp: true
- Status: Su_Stoop
Icon: EFST_SU_STOOP
@@ -6678,6 +6760,7 @@ Body:
Flags:
NoRemoveOnDead: true
NoClearbuff: true
RemoveOnHermode: true
- Status: Geffen_Magic2
Icon: EFST_GEFFEN_MAGIC2
CalcFlags:
@@ -6960,8 +7043,7 @@ Body:
NoBanishingBuster: true
NoClearance: true
NoClearbuff: true
RemoveOnMapWarp: true
NoSave: true
RemoveOnChangeMap: true
- Status: Entry_Queue_Apply_Delay
Icon: EFST_ENTRY_QUEUE_APPLY_DELAY
Flags:
@@ -7045,7 +7127,7 @@ Body:
Icon: EFST_FLASHKICK
DurationLookup: SJ_FLASHKICK
Flags:
RemoveOnMapWarp: true
RemoveOnChangeMap: true
NoBanishingBuster: true
NoDispell: true
NoClearance: true
@@ -7064,7 +7146,7 @@ Body:
NoClearance: true
StopAttacking: true
RemoveOnDamaged: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
Fail:
Bite: true
- Status: Starstance
@@ -7629,7 +7711,7 @@ Body:
BlEffect: true
DisplayPc: true
OverlapIgnoreLevel: true
RemoveOnMapWarp: true
RemoveOnChangeMap: true
NoBanishingBuster: true
NoDispell: true
NoClearance: true

View File

@@ -1419,6 +1419,7 @@ This will also send a packet to clients causing them to close.
@reloadstatusdb
@reloadachievementdb
@reloadattendancedb
@reloadbarterdb
Reloads a database or configuration file.
@@ -1427,10 +1428,11 @@ Databases:
-- itemdb: Item Database
-- mobdb: Monster Database
-- questdb: Quest Database
-- script: NPC Scripts
-- script: NPC Scripts and Barter Database
-- skilldb: Skill Database
-- achievementdb: Achievement Database
-- attendancedb: Attendance Database
-- barterdb: Barter Database
Configuration files:
-- atcommand: Atcommand Settings
@@ -1450,11 +1452,12 @@ Affected files:
-- msgconf: atcommands.yml
-- pcdb: statpoint.yml, job_exp.yml, skill_tree.yml, attr_fix.yml, job_stats.yml, job_basepoints.yml, level_penalty.yml
-- questdb: quest_db.yml
-- script: /npc/*.txt, /npc/*.conf
-- script: /npc/*.txt, /npc/*.conf, /npc/barters.yml
-- skilldb: skill_db.yml, skill_nocast_db.txt, skill_changematerial_db.txt, skill_damage_db.txt, abra_db.yml, create_arrow_db.yml, produce_db.txt, spellbook_db.yml, magicmushroom_db.yml
-- statusdb: attr_fix.yml, size_fix.yml, refine.yml
-- achievementdb: achievement_db.yml
-- attendancedb: attendance.yml
-- barterdb: /npc/barters.yml
Restriction:
- Used from 'atcommand' or 'useatcmd'. For @reload & @reloadscript

View File

@@ -159,7 +159,8 @@ executed, it is affected by spawn rates in 'battle_athena.conf'.
Delay1 and delay2 control monster respawn delays - the first one is the fixed
base respawn time, and the second is random variance on top of the base time.
Both values are given in milliseconds (1000 = 1 second).
Note that the server also enforces a minimum respawn delay of 5 seconds.
Note that the server also enforces a minimum respawn delay of 1 second (See
/conf/battle/monster.conf::mob_respawn_time).
Event is a script event to be executed when the mob is killed. The event must
be in the form "NPCName::OnEventName" to execute, and the event name label
@@ -2730,7 +2731,7 @@ See 'getequipid' for a full list of valid equipment slots.
Given the database ID number of an item, this function will return the text
stored in the 'Name' field in item_db_*.yml for text version
or 'name_english' field for SQL version.
or 'name_english' field for SQL version. The function returns "null" if the item doesn't exist.
---------------------------------------
@@ -6579,6 +6580,28 @@ Examples:
---------------------------------------
macro_detector({<account ID>});
macro_detector({"<character name>"});
This command will display the captcha UI challenge onto the invoking character or the given <account ID>/<character name>.
Example:
// Use 'getareaunits' to gather an area of players to test.
// Build an int array of the account IDs.
.@num = getareaunits(BL_PC, "prontera", 150, 150, 160, 160, .@array[0]);
mes "The number of Players in Prontera in between 150x150 and 160x160 is " + .@num + " .";
mes "Players to challenge:";
freeloop(1); // If the list is too big
for(.@i = 0; .@i < getarraysize(.@array); .@i++) {
mes (.@i + 1) + " " + convertpcinfo(.@array[.@i], CPC_NAME);
macro_detector .@array[.@i];
}
freeloop(0);
end;
---------------------------------------
==================================
|5.- Mob / NPC -related commands.|
==================================
@@ -9647,9 +9670,13 @@ returns an empty string instead.
*instance_id({<instance mode>})
Returns the unique instance ID of the given mode. By default it returns the
attached script instance. If <instance mode> is provided then the instance
of the currently attached player is used. If that fails, the function will return 0.
Returns the unique instance ID of the given mode.
By default (no parameter given) the command returns the instance ID from the attached NPC.
If <instance mode> is provided the instance ID of the currently attached player is returned.
If that fails, the function will return 0.
Please note that the command always requires the parameter <instance mode> to get the instance ID of an attached player!
Instance Mode options:
IM_CHAR: Attached to character.
@@ -9657,6 +9684,13 @@ Instance Mode options:
IM_GUILD: Attached to character's guild.
IM_CLAN: Attached to character's clan.
Examples:
// Example with an attached player :
npctalk "The current instance ID (mode party) from the attached player is : " + instance_id(IM_PARTY);
// Example with an attached NPC on an instance map :
npctalk "The current instance ID from the attached NPC is : " + instance_id();
---------------------------------------
*instance_warpall "<map name>",<x>,<y>{,<instance id>};

View File

@@ -3,7 +3,7 @@
//===== By: ==================================================
//= rAthena Dev Team
//===== Last Updated: ========================================
//= 20221013
//= 20221216
//===== Description: =========================================
//= Explanation of the status.yml file and structure.
//============================================================
@@ -226,11 +226,13 @@ Flags: Various status flags for specific status change events.
RemoveOnRefresh - Removed by RK_REFRESH.
RemoveOnLuxAnima - Removed by RK_LUXANIMA.
RemoveOnMapWarp - Removed when warping to another map.
RemoveOnChangeMap - Removed when changing map-server.
RemoveChemicalProtect - Removed by AM_CP_ARMOR/AM_CP_HELM/AM_CP_SHIELD/AM_CP_WEAPON.
RemoveElementalOption - Removed by elemental changing modes/quitting/EL_TIDAL_WEAPON/EL_WATER_SCREEN on the master and elemental.
RemoveOnUnequip - Removed when unequipping any type of equipment.
RemoveOnUnequipWeapon - Removed when unequipping a weapon.
RemoveOnUnequipArmor - Removed when unequipping an armor.
RemoveOnHermode - Removed by CG_HERMODE.
StopAttacking - Makes the unit stop attacking.
StopCasting - Makes the unit stop casting skills.

12
doc/yaml/db/item_cash.yml Normal file
View File

@@ -0,0 +1,12 @@
###########################################################################
# Item Cash Database
###########################################################################
#
# Item Cash Settings
#
###########################################################################
# - Tab Cash shop tab. Available tabs are New, Hot, Limited, Rental, Permanent, Scrolls, Consumables, Other, Sale.
# Items: List of possible items.
# - Item Item name.
# Price Item cost in cash points (#CASHPOINTS).
###########################################################################

View File

@@ -127,13 +127,14 @@ function Restrict {
Towns:
// --------------------------------------------------
menu "Prontera",T1, "Alberta",T2, "Aldebaran",T3, "Amatsu",T4, "Ayothaya",T5,
"Brasilis",T6, "Comodo",T7, "Dewata",T8, "Eclage",T9, "Einbech",T10,
"Einbroch",T11, "El Dicastes",T12, "Geffen",T13, "Kunlun",T14, "Hugel",T15,
"Izlude",T16, "Jawaii",T17, "Lasagna",T18, "Lighthalzen",T19, "Luoyang",T20,
"Lutie",T21, "Malangdo",T22, "Malaya",T23, "Manuk",T24,
"Midgarts Expedition Camp",T25, "Mora",T26, "Morocc",T27, "Moscovia",T28,
"Nameless Island",T29, "Niflheim",T30, "Payon",T31, "Rachel",T32, "Splendide",T33,
"Thor Camp",T34, "Umbala",T35, "Veins",T36, "Juno",T37;
"Brasilis",T6, "Comodo",T7, "Dewata",T8, "Eclage",T9, "Einbech",T10,
"Einbroch",T11, "El Dicastes",T12, "Geffen",T13, "Hugel",T14, "Ice Castle",T15,
"Izlude",T16, "Jawaii",T17, "Juno",T18, "Kunlun",T19, "Lasagna",T20,
"Lighthalzen",T21, "Luoyang",T22, "Lutie",T23, "Malangdo",T24, "Malaya",T25,
"Manuk",T26, "Midgarts Expedition Camp",T27, "Mora",T28, "Morocc",T29, "Moscovia",T30,
"Nameless Island (Day)",T31, "Nameless Island (Night)",T32, "Niflheim",T33, "Payon",T34, "Rachel",T35,
"Rockridge",T36, "Special Security Area, Cor",T37, "Splendide",T38, "Thor Camp",T39, "Umbala",T40,
"Varmundt's Mansion",T41, "Veins",T42, "Verus Findspot",T43, "Wolf Village",T44;
T1: Go("prontera",155,183);
T2: Go("alberta",28,234);
@@ -152,34 +153,47 @@ T11: Go("einbroch",64,200);
T12: Restrict("RE");
Go("dicastes01",198,187);
T13: Go("geffen",119,59);
T14: Go("gonryun",160,120);
T15: Go("hugel",96,145);
T14: Go("hugel",96,145);
T15: Restrict("RE");
Go("icecastle",185,212);
T16: Go("izlude",128,(checkre(3)?146:114));
T17: Go("jawaii",251,132);
T18: Restrict("RE");
T18: Go("yuno",157,51);
T19: Go("gonryun",160,120);
T20: Restrict("RE");
Go("lasagna",193,182);
T19: Go("lighthalzen",158,92);
T20: Go("louyang",217,100);
T21: Go("xmas",147,134);
T22: Restrict("RE");
T21: Go("lighthalzen",158,92);
T22: Go("louyang",217,100);
T23: Go("xmas",147,134);
T24: Restrict("RE");
Go("malangdo",140,114);
T23: Restrict("RE");
T25: Restrict("RE");
Go("malaya",231,200);
T24: Go("manuk",282,138);
T25: Go("mid_camp",210,288);
T26: Restrict("RE");
T26: Go("manuk",282,138);
T27: Go("mid_camp",210,288);
T28: Restrict("RE");
Go("mora",55,146);
T27: Go("morocc",156,93);
T28: Go("moscovia",223,184);
T29: Go("nameless_n",256,215);
T30: Go("niflheim",202,174);
T31: Go("payon",179,100);
T32: Go("rachel",130,110);
T33: Go("splendide",201,147);
T34: Go("thor_camp",246,68);
T35: Go("umbala",97,153);
T36: Go("veins",216,123);
T37: Go("yuno",157,51);
T29: Go("morocc",156,93);
T30: Go("moscovia",223,184);
T31: Go("nameless_i",256,215);
T32: Go("nameless_n",256,215);
T33: Go("niflheim",202,174);
T34: Go("payon",179,100);
T35: Go("rachel",130,110);
T36: Restrict("RE");
Go("harboro1",298,206);
T37: Restrict("RE");
Go("sp_cor",160,166);
T38: Go("splendide",201,147);
T39: Go("thor_camp",246,68);
T40: Go("umbala",97,153);
T41: Restrict("RE");
Go("ba_maison",72,146);
T42: Go("veins",216,123);
T43: Restrict("RE");
Go("verus04",123,250);
T44: Restrict("RE");
Go("wolfvill",144,144);
// --------------------------------------------------
Fields:
@@ -188,13 +202,14 @@ T37: Go("yuno",157,51);
menu "Amatsu Fields",F1, "Ayothaya Fields",F2, "Bifrost Fields", F3,
"Brasilis Fields",F4, "Comodo Fields",F5, "Dewata Fields",F6,
"Eclage Fields",F7, "Einbroch Fields",F8, "El Dicastes Fields",F9,
"Geffen Fields",F10, "Kunlun Fields",F11, "Hugel Fields",F12,
"Lasagna Fields",F13, "Lighthalzen Fields",F14, "Luoyang Field",F15,
"Lutie Field",F16, "Malaya Fields",F17, "Manuk Fields",F18,
"Mjolnir Fields",F19, "Moscovia Fields",F20, "Niflheim Fields",F21,
"Payon Forests",F22, "Prontera Fields",F23, "Rachel Fields",F24,
"Sograt Deserts",F25, "Splendide Fields",F26, "Umbala Fields",F27,
"Veins Fields",F28, "Juno Fields",F29;
"Frozen Scale Fields",F10, "Geffen Fields",F11, "Grey Wolf Forest",F12,
"Hugel Fields",F13, "Juno Fields",F14, "Kiwawa Desert",F15,
"Kunlun Fields",F16, "Lasagna Fields",F17, "Lighthalzen Fields",F18,
"Luoyang Field",F19, "Lutie Field",F20, "Malaya Fields",F21,
"Manuk Fields",F22, "Mjolnir Fields",F23, "Moscovia Fields",F24,
"Niflheim Fields",F25, "Payon Forests",F26, "Prontera Fields",F27,
"Rachel Fields",F28, "Sograt Deserts",F29, "Splendide Fields",F30,
"Umbala Fields",F31, "Veins Fields",F32;
F1: setarray @c[2],190,197;
Disp("Amatsu Field",1,1); Pick("ama_fild");
@@ -221,43 +236,55 @@ F8: Restrict("Pre-RE",2,10);
F9: Restrict("RE");
setarray @c[2],143,132,143,217;
Disp("El Dicastes Field",1,2); Pick("dic_fild");
F10: Restrict("Pre-RE",13,15);
F10: Restrict("RE");
setarray @c[2],378,223,223,18,365,241,140,280;
Disp("Frozen Scale Hill:Frozen Scale Plains:Frozen Scale Glacier:Frozen Tail"); Pick("","jor_back1","jor_back2","jor_back3","jor_tail");
F11: Restrict("Pre-RE",13,15);
setarray @c[0],46,199,213,204,195,212,257,192,188,171,166,263,248,158,195,191,186,183,221,117,178,218,136,328,240,181,235,235,211,185;
Disp("Geffen Field",0,14); Pick("gef_fild",1);
F11: setarray @c[2],220,227;
Disp("Kunlun Field",1,1); Pick("gon_fild");
F12: Restrict("Pre-RE",3,7);
F12: Restrict("RE");
setarray @c[2],22,315,122,388;
Disp("Grey Wolf Forest",1,2); Pick("gw_fild");
F13: Restrict("Pre-RE",3,7);
setarray @c[2],268,101,222,193,232,185,252,189,196,106,216,220,227,197;
Disp("Hugel Field",1,7); Pick("hu_fild");
F13: Restrict("RE");
F14: Restrict("Pre-RE",5,10);
setarray @c[2],189,224,192,207,221,157,226,199,223,177,187,232,231,174,196,203,183,214,200,124,195,226,210,304;
Disp("Juno Field",1,12); Pick("yuno_fild");
F15: Restrict("RE");
setarray @c[2],38,246,31,207;
Disp("Kiwawa Desert",1,2); Pick("","rockrdg1","rockrdg2");
F16: setarray @c[2],220,227;
Disp("Kunlun Field",1,1); Pick("gon_fild");
F17: Restrict("RE");
setarray @c[2],344,371,20,98;
Disp("Lasagna Field",1,2); Pick("lasa_fild");
F14: setarray @c[2],240,179,185,235,240,226;
F18: setarray @c[2],240,179,185,235,240,226;
Disp("Lighthalzen Field",1,3); Pick("lhz_fild");
F15: setarray @c[2],229,187;
F19: setarray @c[2],229,187;
Disp("Luoyang Field",1,1); Pick("lou_fild");
F16: setarray @c[2],115,145;
F20: setarray @c[2],115,145;
Disp("Lutie Field",1,1); Pick("xmas_fild");
F17: Restrict("RE");
F21: Restrict("RE");
setarray @c[2],40,272,207,180;
Disp("Malaya Field",1,2); Pick("ma_fild");
F18: setarray @c[2],35,236,35,262,84,365;
F22: setarray @c[2],35,236,35,262,84,365;
Disp("Manuk Field",1,3); Pick("man_fild");
F19: setarray @c[2],204,120,175,193,208,213,179,180,181,240,195,270,235,202,188,215,205,144,245,223,180,206,196,208;
F23: setarray @c[2],204,120,175,193,208,213,179,180,181,240,195,270,235,202,188,215,205,144,245,223,180,206,196,208;
Disp("Mjolnir Field",1,12); Pick("mjolnir_");
F20: setarray @c[2],82,104,131,147;
F24: setarray @c[2],82,104,131,147;
Disp("Moscovia Field",1,2); Pick("mosk_fild");
F21: setarray @c[2],215,229,167,234;
F25: setarray @c[2],215,229,167,234;
Disp("Niflheim Field",1,2); Pick("nif_fild");
F22: Restrict("Pre-RE",5,11);
F26: Restrict("Pre-RE",5,11);
setarray @c[2],158,206,151,219,205,148,186,247,134,204,193,235,200,177,137,189,201,224,160,205,194,150;
Disp("Payon Forest",1,11); Pick("pay_fild");
F23: setarray @c[0],208,227,190,206,240,206,190,143,307,252,239,213,185,188,193,194,187,218,210,183,195,149,198,164;
F27: setarray @c[0],208,227,190,206,240,206,190,143,307,252,239,213,185,188,193,194,187,218,210,183,195,149,198,164;
Disp("Prontera Field",0,11); Pick("prt_fild",1);
F24: Restrict("Pre-RE",2,7,9,10,11,13);
F28: Restrict("Pre-RE",2,7,9,10,11,13);
setarray @c[2],192,162,235,166,202,206,202,208,225,202,202,214,263,196,217,201,87,121,277,181,221,185,175,200,174,197;
Disp("Rachel Field",1,13); Pick("ra_fild");
F25: if(.Satan_Morocc){
F29: if(.Satan_Morocc){
setarray @c[2],219,205,177,206,194,182,224,170,198,216,156,187,185,263,206,228,208,238,209,223,85,97,207,202,31,195,38,195;
Disp("Sograt Desert 1:Sograt Desert 2:Sograt Desert 3:Sograt Desert 7:Sograt Desert 11:Sograt Desert 12:Sograt Desert 13:Sograt Desert 16:Sograt Desert 17:Sograt Desert 18:Sograt Desert 19:Sograt Desert 20:Sograt Desert 21:Sograt Desert 22");
Pick("","moc_fild01","moc_fild02","moc_fild03","moc_fild07","moc_fild11","moc_fild12","moc_fild13","moc_fild16","moc_fild17","moc_fild18","moc_fild19","moc_fild20","moc_fild21","moc_fild22");
@@ -265,133 +292,194 @@ F25: if(.Satan_Morocc){
setarray @c[2],219,205,177,206,194,182,146,297,204,197,275,302,224,170,139,123,101,110,341,39,198,216,156,187,185,263,223,222,170,257,206,228,208,238,209,223,85,97;
Disp("Sograt Desert",1,19); Pick("moc_fild");
}
F26: setarray @c[2],175,186,236,184,188,204;
F30: setarray @c[2],175,186,236,184,188,204;
Disp("Splendide Field",1,3); Pick("spl_fild");
F27: setarray @c[2],217,206,223,221,237,215,202,197;
F31: setarray @c[2],217,206,223,221,237,215,202,197;
Disp("Umbala Field",1,4); Pick("um_fild");
F28: Restrict("Pre-RE",5);
F32: Restrict("Pre-RE",5);
setarray @c[2],186,175,196,370,222,45,51,250,202,324,150,223,149,307;
Disp("Veins Field",1,7); Pick("ve_fild");
F29: Restrict("Pre-RE",5,10);
setarray @c[2],189,224,192,207,221,157,226,199,223,177,187,232,231,174,196,203,183,214,200,124,195,226,210,304;
Disp("Juno Field",1,12); Pick("yuno_fild");
// --------------------------------------------------
Dungeons:
// --------------------------------------------------
@d = true;
menu "Abyss Lakes",D1, "Amatsu Dungeon",D2, "Anthell",D3,
"Ayothaya Dungeon",D4, "Beach Dungeon",D5, "Bifrost Tower",D42,
"Bio Labs",D6, "Brasilis Dungeon",D7, "Byalan Dungeon",D8, "Clock Tower",D9,
"Coal Mines",D10, "Culvert",D11, "Cursed Abbey",D12, "Dewata Dungeon",D13,
"Einbroch Dungeon",D14, "Gefenia",D15, "Geffen Dungeon",D16,
"Glast Heim",D17, "Kunlun Dungeon",D18, "Hidden Dungeon",D19,
"Ice Dungeon",D20, "Juperos",D21, "Kiel Dungeon",D22, "Lasagna Dungeon",D23,
"Luoyang Dungeon",D24, "Magma Dungeon",D25, "Malangdo Dungeon",D26,
"Moscovia Dungeon",D27, "Nidhogg's Dungeon",D28, "Odin Temple",D29,
"Orc Dungeon",D30, "Payon Dungeon",D31, "Pyramids",D32, "Rachel Sanctuary",D33,
"Scaraba Hole",D34, "Sphinx",D35, "Sunken Ship",D36, "Thanatos Tower",D37,
"Thor Volcano",D38, "Toy Factory",D39, "Turtle Dungeon",D40, "Umbala Dungeon",D41;
menu "Abandoned Lab Amicitia",D1, "Abyss Lakes",D2, "Amatsu Dungeon",D3,
"Anthell",D4, "Ayothaya Dungeon",D5, "Beach Dungeon",D6,
"Bifrost Tower",D7, "Bio Labs",D8, "Brasilis Dungeon",D9,
"Byalan Dungeon",D10, "Clock Tower",D11, "Coal Mines",D12,
"Culvert",D13, "Cursed Abbey",D14, "Dewata Dungeon",D15,
"Einbroch Dungeon",D16, "Flame Basin",D17, "Gefenia",D18,
"Geffen Dungeon",D19, "Glast Heim",D20, "Hidden Dungeon",D21,
"Ice Dungeon",D22, "Illusion Dungeon",D23, "Issgard Dungeon",D24,
"Juperos",D25, "Kiel Dungeon",D26, "Kunlun Dungeon",D27,
"Lasagna Dungeon",D28, "Luoyang Dungeon",D29, "Magma Dungeon",D30,
"Malangdo Dungeon",D31, "Moscovia Dungeon",D32, "Nidhogg's Dungeon",D33,
"Niflheim Dungeon",D34, "Odin Temple",D35, "Orc Dungeon",D36,
"Oz Labyrinth Dungeon",D37, "Payon Dungeon",D38, "Prontera Underground",D39,
"Pyramids",D40, "Rachel Sanctuary",D41, "Rock Ridge Dungeon",D42,
"Rudus Dungeon",D43, "Scaraba Hole",D44, "Sphinx",D45,
"Sunken Ship",D46, "Thanatos Tower",D47, "Thor Volcano",D48,
"Toy Factory",D49, "Turtle Dungeon",D50, "Umbala Dungeon",D51,
"Varmundt's Dungeon",D52, "Verus Area",D53;
D1: setarray @c[2],261,272,275,270,116,27;
Disp("Abyss Lakes",1,3); Pick("abyss_");
D2: setarray @c[2],228,11,34,41,119,14;
D1: Restrict("RE");
setarray @c[2],253,244,145,278;
Disp("1st Floor - Comprehensive Lab:2nd Floor - Intensive Culture Room"); Pick("","amicitia1","amicitia2");
D2: Restrict("RE",4);
setarray @c[2],261,272,275,270,116,27,169,159;
Disp("Abyss Lakes",1,4); Pick("abyss_");
D3: setarray @c[2],228,11,34,41,119,14;
Disp("Amatsu Dungeon",1,3); Pick("ama_dun");
D3: setarray @c[2],35,262,168,170;
D4: setarray @c[2],35,262,168,170;
Disp("Anthell",1,2); Pick("anthell");
D4: setarray @c[2],275,19,24,26;
D5: setarray @c[2],275,19,24,26;
Disp("Ancient Shrine Maze:Inside Ancient Shrine"); Pick("ayo_dun");
D5: setarray @c[2],266,67,255,244,23,260;
D6: setarray @c[2],266,67,255,244,23,260;
Disp("Beach Dungeon",1,3); Pick("","beach_dun","beach_dun2","beach_dun3");
D6: Restrict("RE",4);
setarray @c[2],150,288,150,18,140,134,244,52;
Disp("Bio Lab",1,4); Pick("lhz_dun");
D7: Restrict("RE");
setarray @c[2],57,13,64,88,45,14,26,23;
Disp("Bifrost Tower",1,4); Pick("ecl_tdun");
D8: Restrict("RE",4,5);
setarray @c[2],150,288,150,18,140,134,244,52,100,202;
Disp("Bio Lab 1:Bio Lab 2:Bio Lab 3:Bio Lab 4:Tomb of the Fallen"); Pick("","lhz_dun01","lhz_dun02","lhz_dun03","lhz_dun04","lhz_dun_n");
D9: Restrict("RE");
setarray @c[2],87,47,262,262;
Disp("Brasilis Dungeon",1,2); Pick("bra_dun");
D8: Restrict("RE",6);
setarray @c[0],168,168,253,252,236,204,32,63,26,27,141,187;
Disp("Byalan Dungeon",1,6); Pick("iz_dun",1);
D9: setarray @c[2],199,159,148,283,65,147,56,155,297,25,127,169,277,178,268,74;
Disp("Clock Tower 1:Clock Tower 2:Clock Tower 3:Clock Tower 4:Basement 1:Basement 2:Basement 3:Basement 4");
Pick("","c_tower1","c_tower2","c_tower3","c_tower4","alde_dun01","alde_dun02","alde_dun03","alde_dun04");
D10: setarray @c[2],52,17,381,343,302,262;
D10: Restrict("RE",6);
setarray @c[0],168,168,253,252,236,204,32,63,26,27,141,187;
Disp("Byalan Dungeon",1,6); Pick("iz_dun",1);
D11: Restrict("RE",9,10,11);
setarray @c[2],199,159,148,283,65,147,56,155,297,25,127,169,277,178,268,74,266,27,60,142,79,39;
Disp("Clock Tower 1:Clock Tower 2:Clock Tower 3:Clock Tower 4:Basement 1:Basement 2:Basement 3:Basement 4:Nightmare Clock Tower, 2nd Floor:Nightmare Clock Tower, 3rd Floor:Unknown Basement");
Pick("","c_tower1","c_tower2","c_tower3","c_tower4","alde_dun01","alde_dun02","alde_dun03","alde_dun04","c_tower2_","c_tower3_","clock_01");
D12: setarray @c[2],52,17,381,343,302,262;
Disp("Coal Mines",1,3); Pick("mjo_dun");
D11: setarray @c[2],131,247,19,19,180,169,100,92;
D13: setarray @c[2],131,247,19,19,180,169,100,92;
Disp("Culvert",1,4); Pick("","prt_sewb1","prt_sewb2","prt_sewb3","prt_sewb4");
D12: setarray @c[2],51,14,150,11,120,10;
D14: setarray @c[2],51,14,150,11,120,10;
Disp("Cursed Abbey",1,3); Pick("abbey");
D13: Restrict("RE");
D15: Restrict("RE");
setarray @c[2],285,160,299,29;
Disp("Dewata Dungeon",1,2); Pick("dew_dun");
D14: setarray @c[2],22,14,292,290;
Disp("Einbroch Dungeon",1,2); Pick("ein_dun");
D15: setarray @c[2],40,103,203,34,266,168,130,272;
D16: Restrict("RE",3);
setarray @c[2],22,14,292,290,269,279;
Disp("Einbroch Dungeon",1,3); Pick("ein_dun");
D17: Restrict("RE");
Go("moro_vol",97,107);
D18: setarray @c[2],40,103,203,34,266,168,130,272;
Disp("Gefenia",1,4); Pick("gefenia",0);
D16: setarray @c[0],104,99,115,236,106,132,203,200;
D19: setarray @c[0],104,99,115,236,106,132,203,200;
Disp("Geffen Dungeon",1,4); Pick("gef_dun",1);
D17: setarray @c[2],370,304,199,29,104,25,150,15,157,287,147,15,258,255,108,291,171,283,68,277,156,7,12,7,133,271,224,274,14,70,150,14;
Disp("Entrance:Castle 1:Castle 2:Chivalry 1:Chivalry 2:Churchyard:Culvert 1:Culvert 2:Culvert 3:Culvert 4:St. Abbey:Staircase Dungeon:Underground Cave 1:Underground Cave 2:Underground Prison 1:Underground Prison 2");
Pick("","glast_01","gl_cas01","gl_cas02","gl_knt01","gl_knt02","gl_chyard","gl_sew01","gl_sew02","gl_sew03","gl_sew04","gl_church","gl_step","gl_dun01","gl_dun02","gl_prison","gl_prison1");
D18: setarray @c[2],153,53,28,113,68,16;
Disp("Kunlun Dungeon",1,3); Pick("gon_dun");
D19: setarray @c[2],176,7,93,20,23,8;
D20: Restrict("RE",17,18,19);
setarray @c[2],370,304,199,29,104,25,150,15,157,287,147,15,258,255,108,291,171,283,68,277,156,7,12,7,133,271,224,274,14,70,150,14,104,31,148,144,199,29;
Disp("Entrance:Castle 1:Castle 2:Chivalry 1:Chivalry 2:Churchyard:Culvert 1:Culvert 2:Culvert 3:Culvert 4:St. Abbey:Staircase Dungeon:Underground Cave 1:Underground Cave 2:Underground Prison 1:Underground Prison 2:Castle 2 - Nightmare Mode:Churchyard - Nightmare Mode:Abyss Glastheim Castle F1");
Pick("","glast_01","gl_cas01","gl_cas02","gl_knt01","gl_knt02","gl_chyard","gl_sew01","gl_sew02","gl_sew03","gl_sew04","gl_church","gl_step","gl_dun01","gl_dun02","gl_prison","gl_prison1","gl_cas02_","gl_chyard_","gl_cas01_");
D21: setarray @c[2],99,31,93,20,182,88;
Disp("Hidden Dungeon",1,3); Pick("prt_maze");
D20: setarray @c[2],157,14,151,155,149,22,33,158;
D22: setarray @c[2],157,14,151,155,149,22,33,158;
Disp("Ice Dungeon",1,4); Pick("ice_dun");
D21: setarray @c[2],140,51,53,247,37,63,150,285;
Disp("Entrance:Juperos 1:Juperos 2:Core");
Pick("","jupe_cave","juperos_01","juperos_02","jupe_core");
D22: setarray @c[2],28,226,41,198;
D23: menu "Illusion of Abyss",SubD1, "Illusion of Frozen",SubD2, "Illusion of Labyrinth",SubD3,
"Illusion of Luanda",SubD4, "Illusion of Moonlight",SubD5, "Illusion of Teddy Bear",SubD6,
"Illusion of Twins",SubD7, "Illusion of Underwater",SubD8, "Illusion of Vampire",SubD9;
SubD1: Restrict("RE");
setarray @c[2],132,189,100,192;
Disp("Desolate Village:Bleak Turtle Palace"); Pick("","tur_d03_i","tur_d04_i");
SubD2: Restrict("RE");
Go("ice_d03_i",149,22);
SubD3: Restrict("RE");
Go("prt_mz03_i",100,100);
SubD4: Restrict("RE");
Go("com_d02_i",250,245);
SubD5: Restrict("RE");
Go("pay_d03_i",140,44);
SubD6: Restrict("RE");
Go("ein_d02_i",164,184);
SubD7: Restrict("RE");
Go("ant_d02_i",168,170);
SubD8: Restrict("RE");
setarray @c[2],130,230,141,188;
Disp("Deep Sea Cave",1,2); Pick("","iz_d04_i","iz_d05_i");
SubD9: Restrict("RE");
Go("gef_d01_i",114,216);
D24: Restrict("RE");
setarray @c[2],112,15,280,87,112,12,274,85;
Disp("Abandoned Pit Floor 1:Abandoned Pit Floor 2:Snake God's Warmth 1st Floor:Snake God's Warmth 2nd Floor"); Pick("","jor_ab01","jor_ab02","jor_dun01","jor_dun02");
D25: Restrict("RE",5);
setarray @c[2],140,51,53,247,37,63,150,285,146,215;
Disp("Entrance:Juperos 1:Juperos 2:Core:Eastern Ruins of Juperos");
Pick("","jupe_cave","juperos_01","juperos_02","jupe_core","ver_eju");
D26: setarray @c[2],28,226,41,198;
Disp("Kiel Dungeon",1,2); Pick("kh_dun");
D23: Restrict("RE");
D27: setarray @c[2],153,53,28,113,68,16;
Disp("Kunlun Dungeon",1,3); Pick("gon_dun");
D28: Restrict("RE");
setarray @c[2],24,143,22,171,190,18;
Disp("Lasagna Dungeon",1,3); Pick("lasa_dun");
D24: setarray @c[2],218,196,282,20,165,38;
D29: setarray @c[2],218,196,282,20,165,38;
Disp("The Royal Tomb:Inside the Royal Tomb:Suei Long Gon"); Pick("lou_dun");
D25: setarray @c[2],126,68,47,30;
Disp("Magma Dungeon",1,2); Pick("mag_dun");
D26: Restrict("RE");
D30: Restrict("RE",3);
setarray @c[2],126,68,47,30,118,113;
Disp("Magma Dungeon",1,3); Pick("mag_dun");
D31: Restrict("RE");
setarray @c[2],33,230;
Disp("Malangdo Dungeon",1,1); Pick("mal_dun");
D27: setarray @c[2],189,48,165,30,32,135;
D32: setarray @c[2],189,48,165,30,32,135;
Disp("Moscovia Dungeon",1,3); Pick("mosk_dun");
D28: setarray @c[2],61,239,60,271;
D33: setarray @c[2],61,239,60,271;
Disp("Nidhogg's Dungeon",1,2); Pick("nyd_dun");
D29: setarray @c[2],298,167,224,149,266,280;
Disp("Odin Temple",1,3); Pick("odin_tem");
D30: setarray @c[2],32,170,21,185;
D34: Restrict("RE");
setarray @c[2],145,90,150,20;
Disp("Niflheim Dungeon - 1st Floor:Niflheim Dungeon - 2nd Floor"); Pick("nif_dun");
D35: Restrict("RE",4);
setarray @c[2],298,167,224,149,266,280,276,236;
Disp("Odin Temple 1:Odin Temple 2:Odin Temple 3:Odin Past"); Pick("","odin_tem01","odin_tem02","odin_tem03","odin_past");
D36: setarray @c[2],32,170,21,185;
Disp("Orc Dungeon",1,2); Pick("orcsdun");
D31: setarray @c[0],21,183,19,33,19,63,155,159,201,204;
D37: Restrict("RE");
setarray @c[2],21,191,141,277;
Disp("Oz Labyrinth Floor 1:Oz Labyrinth Floor 2"); Pick("oz_dun");
D38: setarray @c[0],21,183,19,33,19,63,155,159,201,204;
Disp("Payon Dungeon",1,5); Pick("pay_dun",1);
D32: Restrict("RE",7,8);
D39: Restrict("RE");
setarray @c[2],159,289,155,353;
Disp("Prontera Underground Prison:Prontera Invasion"); Pick("","prt_prison","prt_q");
D40: Restrict("RE",7,8);
setarray @c[2],192,9,10,192,100,92,181,11,94,96,192,8,94,96,192,8;
Disp("Pyramids 1:Pyramids 2:Pyramids 3:Pyramids 4:Basement 1:Basement 2:Basement 1 - Nightmare Mode:Basement 2 - Nightmare Mode");
Pick("","moc_pryd01","moc_pryd02","moc_pryd03","moc_pryd04","moc_pryd05","moc_pryd06","moc_prydn1","moc_prydn2");
D33: setarray @c[2],140,11,32,21,8,149,204,218,150,9;
D41: setarray @c[2],140,11,32,21,8,149,204,218,150,9;
Disp("Rachel Sanctuary",1,5); Pick("ra_san");
D34: Restrict("RE");
setarray @c[2],364,44,101,141;
Disp("Scaraba Hole",1,2); Pick("dic_dun");
D35: setarray @c[2],288,9,149,81,210,54,10,222,100,99;
D42: Restrict("RE");
setarray @c[2],247,19,281,104;
Disp("Rock Ridge Mine:Underground Waterway Culvert"); Pick("","rockmi1","harboro2");
D43: Restrict("RE");
setarray @c[2],200,377,185,258,366,207,378,178;
Disp("Rudus Dungeon",1,4); Pick("","sp_rudus","sp_rudus2","sp_rudus3","sp_rudus4");
D44: Restrict("RE");
setarray @c[2],364,44,101,141,101,141;
Disp("Scaraba Hole",1,3); Pick("dic_dun");
D45: setarray @c[2],288,9,149,81,210,54,10,222,100,99;
Disp("Sphinx",1,5); Pick("","in_sphinx1","in_sphinx2","in_sphinx3","in_sphinx4","in_sphinx5");
D36: setarray @c[2],69,24,102,27;
D46: setarray @c[2],69,24,102,27;
Disp("Sunken Ship",1,2); Pick("treasure");
D37: setarray @c[2],150,39,150,136,220,158,59,143,62,11,89,221,35,166,93,148,29,107,159,138,19,20,130,52;
D47: setarray @c[2],150,39,150,136,220,158,59,143,62,11,89,221,35,166,93,148,29,107,159,138,19,20,130,52;
Disp("Thanatos Tower",1,12); Pick("tha_t");
D38: setarray @c[2],21,228,75,205,34,272;
D48: setarray @c[2],21,228,75,205,34,272;
Disp("Thor Volcano",1,3); Pick("thor_v");
D39: setarray @c[2],205,15,129,133;
D49: setarray @c[2],205,15,129,133;
Disp("Toy Factory",1,2); Pick("xmas_dun");
D40: setarray @c[2],154,49,148,261,132,189,100,192;
D50: setarray @c[2],154,49,148,261,132,189,100,192;
Disp("Entrance:Turtle Dungeon 1:Turtle Dungeon 2:Turtle Dungeon 3"); Pick("tur_dun");
D41: Restrict("Pre-RE",1,2);
D51: Restrict("Pre-RE",1,2);
setarray @c[2],42,31,48,30,204,78;
Disp("Carpenter's Shop in the Tree:Passage to a Foreign World:Hvergermil's Fountain");
Pick("","um_dun01","um_dun02","yggdrasil01");
D42: Restrict("RE");
setarray @c[2],57,13,64,88,45,14,26,23;
Disp("Bifrost Tower",1,4); Pick("ecl_tdun");
D52: Restrict("RE");
setarray @c[2],275,21,15,115,15,115,159,27,162,36,159,11,156,33,337,333,314,64,163,18,156,20,39,81;
Disp("Sewage Treatment Plant:1st Power Plant:2nd Power Plant:Large Bath Meditathio:Lost Farm Valley:Library Memory Corridor:Upper Floor of Tartaros Storage:Lower Floor of Tartaros Storage:Death Rune:Fire Rune:Grass Rune:Ice Rune"); Pick("","ba_pw02","ba_pw01","ba_pw03","ba_bath","ba_lost","ba_lib","ba_2whs01","ba_2whs02","bl_death","bl_lava","bl_grass","bl_ice");
D53: Restrict("RE");
setarray @c[2],244,61,72,20,122,22;
Disp("Lab-OPTATIO:R&D-WISH:Verus Center Square"); Pick("verus");
// --------------------------------------------------
Castles:

View File

@@ -1,125 +0,0 @@
//===== rAthena Script =======================================
//= Cash Hair Stylist
//===== By: ==================================================
//= Kisuka
//===== Current Version: =====================================
//= 1.0
//===== Compatible With: =====================================
//= rAthena Project
//===== Description: =========================================
//= Exchange cash item, New_Style_Coupon, for new hair styles.
//===== Additional Comments: =================================
//= 1.0 First Version. [Kisuka]
//============================================================
itemmall,19,74,5 script Stylist#cash 91,{
mes "[Stylist]";
mes "Hey, I'm Kaniki.";
mes "I'm here to start a new";
mes "trend by introducing my";
mes "special new hairstyles!";
mes "Give me a ^FF0000New Style Coupon^000000,";
mes "and I'll change your hair~";
next;
if (Sex == SEX_MALE) {
mes "[Kaniki]";
mes "I have two special";
mes "hairstyles for men, the";
mes "Emergency Heal Perm";
mes "and the Aura Blade Cut.";
mes "and aura blade cut.";
next;
cutin "hair_m_24.bmp",4;
mes "[Kaniki]";
mes "This is the Emergency";
mes "Heal Perm. It's a brand";
mes "new style I invented recently.";
mes "What do you think? Cool, huh?";
next;
cutin "",255;
cutin "hair_m_25.bmp",4;
mes "[Kaniki]";
mes "Now this is the Aura";
mes "Blade Cut. You haven't";
mes "seen anything like it";
mes "before, haven't you?";
next;
cutin "",255;
}else{
mes "[Kaniki]";
mes "I have two new hairstyles for";
mes "women, the Assumptio Perm";
mes "and the Soul Changer Cut.";
mes "Do you want to see how";
mes "these styles look?";
next;
cutin "hair_f_24.bmp",4;
mes "[Kaniki]";
mes "This is the Assumptio";
mes "Perm. It'd really good";
mes "on you, wouldn't it?";
next;
cutin "",255;
cutin "hair_f_25.bmp",4;
mes "[Kaniki]";
mes "Next is the Soul";
mes "Changer Cut. What do";
mes "you think? Isn't it nice?";
next;
cutin "",255;
}
mes "[Kaniki]";
mes "Have you decided";
mes "if you'd like me to";
mes "change your hairstyle?";
next;
if(select("Change Hairstyle:Don't Change") == 1) {
if (countitem(7622) > 0) {
mes "[Kaniki]";
mes "Great, you brought";
mes "a New Style Coupon!";
mes "Alright, which hairstyle";
mes "did you want to have?";
next;
if (Sex == SEX_MALE) {
if(select("Emergency Heal Perm:Aura Blade Cut") == 1) {
delitem 7622,1; // New_Style_Coupon
setlook 1,24;
}else{
delitem 7622,1; // New_Style_Coupon
setlook 1,25;
}
}else{
if(select("Assumptio Perm:Soul Changer Cut") == 1) {
delitem 7622,1; // New_Style_Coupon
setlook 1,24;
}else{
delitem 7622,1; // New_Style_Coupon
setlook 1,25;
}
}
mes "[Kaniki]";
mes "There--! It's done!";
mes "How do you like your";
mes "new hair? Well, I hope";
mes "to see you again. Take care!";
close;
}else{
mes "[Kaniki]";
mes "I'm sorry, but I can";
mes "only provide my hairstyling";
mes "service if you bring a New";
mes "Style Coupon. Please come";
mes "back to me after you manage to";
mes "get one of those coupons, okay?";
close;
}
}
mes "[Kaniki]";
mes "Really? Oh, that's too bad.";
mes "Well, if you ever change your";
mes "mind about updating your";
mes "hairstyle, come back";
mes "and let me know, okay?";
close;
}

View File

@@ -14,7 +14,7 @@
// nyd_dun01 - Yggdrasil Root Dungeon
//==================================================
nyd_dun01,0,0 monster Draco 2013,40
nyd_dun01,0,0 monster Draco's Egg 2014,10,0,0,0
nyd_dun01,0,0 monster Draco's Egg 2014,10
nyd_dun01,0,0 monster Aqua Elemental 2016,20
nyd_dun01,0,0 monster Dark Pinguicula 2015,10
nyd_dun01,0,0 monster Rata 2017,2,900000

View File

@@ -84,7 +84,7 @@ prt_maze03,50,150,70,70 monster Vagabond Wolf 1092,1,1920000,150000
prt_maze03,170,170,70,70 monster Mantis 1139,30,60000,30000
prt_maze03,170,170,70,70 monster Eclipse 1093,1,1920000,150000
prt_maze03,23,23,70,70 monster Mastering 1090,1,1920000,150000
prt_maze03,100,100,80,80 monster Baphomet Jr. 1101,25,0,0,0
prt_maze03,100,100,80,80 monster Baphomet Jr. 1101,25
prt_maze03,0,0,0,0 boss_monster Baphomet 1039,1,7200000,600000,1
prt_maze03,61,98,10,10 monster Shining Plant 1083,1,1800000,900000
prt_maze03,61,98,10,10 monster Blue Plant 1079,1,1800000,900000

View File

@@ -391,3 +391,8 @@ que_thr mapflag nobranch
// Sunken Tower
//============================================================
1@ch_u mapflag nobranch
//============================================================
// Cash Mall
//============================================================
itemmall mapflag nobranch

View File

@@ -486,3 +486,8 @@ wolfvill mapflag nomemo
// Illusion of Twins
//============================================================
ant_d02_i mapflag nomemo
//============================================================
// Cash Mall
//============================================================
itemmall mapflag nomemo

View File

@@ -107,3 +107,8 @@ lasa_in01 mapflag nopenalty
conch_in mapflag nopenalty
wolfvill mapflag nopenalty
//============================================================
// Cash Mall
//============================================================
itemmall mapflag nopenalty

View File

@@ -122,3 +122,8 @@ ecl_hub01 mapflag pvp off
que_avan01 mapflag pvp off
dali mapflag pvp off
wolfvill mapflag pvp off
//============================================================
// Cash Mall
//============================================================
itemmall mapflag pvp off

View File

@@ -446,3 +446,9 @@ que_thr mapflag noteleport
1@ch_u mapflag noteleport
1@ch_u mapflag monster_noteleport
1@ch_u mapflag monster_noteleport
//============================================================
// Cash Mall
//============================================================
itemmall mapflag noteleport
itemmall mapflag monster_noteleport

View File

@@ -54,3 +54,4 @@ Footer:
- Path: npc/re/merchants/barters/quests_17_1.yml
- Path: npc/re/merchants/barters/refine.yml
- Path: npc/re/merchants/barters/enchantgrade.yml
- Path: npc/re/merchants/barters/cashmall.yml

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,331 @@
//===== rAthena Script =======================================
//= Cash Mall
//===== Changelogs: ==========================================
//= 1.0 Initial version from replays. [Lemongrass]
//= 1.1 Cash Hair Stylist [Kisuka]
//= 1.2 Updated Hair Stylist [Lemongrass]
//============================================================
prontera,137,125,4 script Cash Sales Guide#prontera::cashmall_warper 4_M_HUMAN_02,{
mes "[Guide]";
mes "Hello~";
mes "This guide wants to be the one to take you to a special place.";
mes "What kind of place is that?";
next;
mes "[Guide]";
mes "It's a place full of mysterious items to collect and sell.";
mes "To buy stuff there you need special money.";
next;
mes "[Guide]";
mes "So, are you ready to go there?";
next;
if (select( "Yes", "No" ) == 2) {
mes "[Guide]";
mes "Okay~";
mes "But don't get frustrated.";
mes "There's always more chances~";
close;
}
mes "[Guide]";
mes "Yeah~ You're really ready.";
mes "Well then, get some good stuff~";
mes "Oops, I forgot. When you come out be sure to come back here.";
mes "Rember this~";
close2;
setarray .@maparray$[0], "prontera", "morocc", "moc_ruins", "geffen", "payon", "lighthalzen", "rachel";
.@return = inarray(.@maparray$[0], strcharinfo(3));
if (.@return > 0)
cashmall_return = .@return;
else // Default to Prontera if not found
cashmall_return = 0;
warp "itemmall",22,43;
end;
}
morocc,164,39,4 duplicate(cashmall_warper) Cash Sales Guide#morocc 4_M_HUMAN_02
moc_ruins,115,143,4 duplicate(cashmall_warper) Cash Sales Guide#moc_ruins 4_M_HUMAN_02
geffen,115,168,4 duplicate(cashmall_warper) Cash Sales Guide#geffen 4_M_HUMAN_02
payon,164,157,4 duplicate(cashmall_warper) Cash Sales Guide#payon 4_M_HUMAN_02
lighthalzen,206,144,4 duplicate(cashmall_warper) Cash Sales Guide#lighthalzen 4_M_HUMAN_02
rachel,128,144,4 duplicate(cashmall_warper) Cash Sales Guide#rachel 4_M_HUMAN_02
itemmall,21,45,4 script Exit Guide#cashmall_exit 4_M_HUMAN_02,{
mes "[Guide]";
mes "Have you had a good time?";
mes "Thank you very much for using our item mall.";
mes "We will continue to bring you valuable items.";
next;
mes "[Guide]";
mes "Would you like to return from where you came from?";
next;
if (select( "Yes", "No" ) == 2) {
mes "[Guide]";
mes "There are still more things to see.";
mes "Have a good time.";
close;
}
mes "[Guide]";
mes "Thank you for coming.";
mes "I'll send you back from where you came from.";
close2;
switch(cashmall_return) {
default:
case 0:
.@returnmap$ = "prontera";
setarray .@xy[0],116,72;
break;
case 1:
.@returnmap$ = "morocc";
setarray .@xy[0],159,46;
break;
case 2:
.@returnmap$ = "moc_ruins";
setarray .@xy[0],109,137;
break;
case 3:
.@returnmap$ = "geffen";
setarray .@xy[0],120,38;
break;
case 4:
.@returnmap$ = "payon";
setarray .@xy[0],161,58;
break;
case 5:
.@returnmap$ = "lighthalzen";
setarray .@xy[0],159,95;
break;
case 6:
.@returnmap$ = "rachel";
setarray .@xy[0],115,125;
break;
}
cashmall_return = 0;
warp .@returnmap$,.@xy[0],.@xy[1];
end;
}
itemmall,41,53,3 script Cat Hand Salesman Macaroon#cashmall 4_M_MERCAT1,{
mes "[Macaroon]";
mes "Welcome!";
mes "Today doesn't come every day!";
mes "Things to see today~ Voila!";
mes "You can only exchange with <ITEM>[[Kachua] Mileage Coupon]<INFO>1000274</INFO></ITEM>!";
mes "Feel free to choose!";
next;
switch( select( "3-1st Job Group Skill Shadow", "3-2nd Job Group Skill Shadow", "Extended Job Group Skill Shadow", "General Shadow by Occupation", "Shadow Cube", "Smelting, Modification, Useful Items", "Drop Box", "Spellbook" ) ){
case 1:
mes "[Macaroon]";
mes "^FF00663-1st Job Group Skill Shadow^000000 you say!";
mes "Here they are!";
close2;
callshop "CachuaCoupon01";
end;
case 2:
mes "[Macaroon]";
mes "^FF00663-2nd Job Group Skill Shadow^000000 you say!";
mes "Here they are!";
close2;
callshop "CachuaCoupon02";
end;
case 3:
mes "[Macaroon]";
mes "^FF0066Extended Job Group Skill Shadow^000000 you say!";
mes "Here they are!";
close2;
callshop "CachuaCoupon03";
end;
case 4:
mes "[Macaroon]";
mes "^FF0066General Shadow by Occupation^000000 you say!";
mes "Here they are!";
close2;
callshop "CachuaCoupon04";
end;
case 5:
mes "[Macaroon]";
mes "^FF0066Shadow Cube^000000 you say!";
mes "Here they are!";
close2;
callshop "CachuaCoupon05";
end;
case 6:
mes "[Macaroon]";
mes "^FF0066Smelting, Modification, Useful Items^000000 you say!";
mes "Here they are!";
close2;
callshop "CachuaCoupon06";
end;
case 7:
mes "[Macaroon]";
mes "^FF0066Drop Box^000000 you say!";
mes "Here they are!";
close2;
callshop "CachuaCoupon07";
end;
case 8:
mes "[Macaroon]";
mes "^FF0066Spellbook^000000 you say!";
mes "Here they are!";
close2;
callshop "CachuaCoupon08";
end;
}
}
itemmall,24,77,4 script Blacksmith Basta#pr 4_M_DWARF,{
if( !getbattleflag( "feature.refineui" ) ){
end;
}
mes "[Blacksmith Basta]";
mes "I have taken over the work of Mighty Hammer, Brock and the Shadow Blacksmith. I will be busy from now on.";
close2;
refineui();
end;
}
itemmall,27,77,4 script Mighty Hammer#im 4_M_DWARF,{
mes "[Blacksmith Mighty Hammer]";
mes "If it is about refining, ask Basta. I am retired.";
close;
}
itemmall,24,74,5 script Blacksmith Brock#im 4_M_HUMAN_01,{
mes "[Blacksmith Brock]";
mes "I am retired now. If it is about refining, make a request to Basta over there.";
close;
}
itemmall,19,74,5 script Stylist#cash 91,{
if( getbattleflag( "feature.stylist" ) ){
mes "[Jeremy]";
mes "Hello cutie~";
mes "I would like you to call me Head Stylist Jeremy.";
next;
if( select( "Change style:End conversation" ) == 2 ){
mes "[Jeremy]";
mes "My shop is always open, so please come back anytime.";
close;
}
close2;
openstylist();
end;
}
mes "[Stylist]";
mes "Hey, I'm Kaniki.";
mes "I'm here to start a new";
mes "trend by introducing my";
mes "special new hairstyles!";
mes "Give me a ^FF0000New Style Coupon^000000,";
mes "and I'll change your hair~";
next;
if (Sex == SEX_MALE) {
mes "[Kaniki]";
mes "I have two special";
mes "hairstyles for men, the";
mes "Emergency Heal Perm";
mes "and the Aura Blade Cut.";
mes "and aura blade cut.";
next;
cutin "hair_m_24.bmp",4;
mes "[Kaniki]";
mes "This is the Emergency";
mes "Heal Perm. It's a brand";
mes "new style I invented recently.";
mes "What do you think? Cool, huh?";
next;
cutin "",255;
cutin "hair_m_25.bmp",4;
mes "[Kaniki]";
mes "Now this is the Aura";
mes "Blade Cut. You haven't";
mes "seen anything like it";
mes "before, haven't you?";
next;
cutin "",255;
}else{
mes "[Kaniki]";
mes "I have two new hairstyles for";
mes "women, the Assumptio Perm";
mes "and the Soul Changer Cut.";
mes "Do you want to see how";
mes "these styles look?";
next;
cutin "hair_f_24.bmp",4;
mes "[Kaniki]";
mes "This is the Assumptio";
mes "Perm. It'd really good";
mes "on you, wouldn't it?";
next;
cutin "",255;
cutin "hair_f_25.bmp",4;
mes "[Kaniki]";
mes "Next is the Soul";
mes "Changer Cut. What do";
mes "you think? Isn't it nice?";
next;
cutin "",255;
}
mes "[Kaniki]";
mes "Have you decided";
mes "if you'd like me to";
mes "change your hairstyle?";
next;
if (select( "Change Hairstyle", "Don't Change" ) == 2) {
mes "[Kaniki]";
mes "Really? Oh, that's too bad.";
mes "Well, if you ever change your";
mes "mind about updating your";
mes "hairstyle, come back";
mes "and let me know, okay?";
close;
}
if (countitem(7622) < 1) {
mes "[Kaniki]";
mes "I'm sorry, but I can";
mes "only provide my hairstyling";
mes "service if you bring a New";
mes "Style Coupon. Please come";
mes "back to me after you manage to";
mes "get one of those coupons, okay?";
close;
}
mes "[Kaniki]";
mes "Great, you brought";
mes "a New Style Coupon!";
mes "Alright, which hairstyle";
mes "did you want to have?";
next;
if (Sex == SEX_MALE) {
if(select("Emergency Heal Perm", "Aura Blade Cut") == 1) {
delitem 7622,1; // New_Style_Coupon
setlook 1,24;
}else{
delitem 7622,1; // New_Style_Coupon
setlook 1,25;
}
}else{
if(select("Assumptio Perm", "Soul Changer Cut") == 1) {
delitem 7622,1; // New_Style_Coupon
setlook 1,24;
}else{
delitem 7622,1; // New_Style_Coupon
setlook 1,25;
}
}
mes "[Kaniki]";
mes "There--! It's done!";
mes "How do you like your";
mes "new hair? Well, I hope";
mes "to see you again. Take care!";
close;
}

View File

@@ -12,11 +12,12 @@
//===== Additional Comments: =================================
//= 1.0 First version.
//= 1.1 Standardizing, grammar and bug fixes. [Euphy]
//= 1.2 Moved to Cash Mall [Lemongrass]
//============================================================
// Main NPC :: 201105_luk_enc
//============================================================
prt_in,28,73,3 script Devil Enchant Master#prq 63,{
itemmall,29,71,3 script Devil Enchant Master#prq 63,{
disable_items;
if (checkweight(1201,1) == 0) {
mes "You are carrying too many items, please reduce it and come back again!";

View File

@@ -8,6 +8,7 @@
//= 1.1 Removed re-roll behavior and fetch materials from db
//= [Secret]
//= 1.2 Added Refine UI [Atemo, Lemongrass]
//= 1.3 Moved to Cash Mall [Lemongrass]
//============================================================
- script ::ShadowBlacksmith -1,{
if( getbattleflag( "feature.refineui" ) ){
@@ -163,4 +164,5 @@
}
//moc_paraup,45,185,5 duplicate(ShadowBlacksmith) Shadow Blacksmith#eden1 4_F_JOB_BLACKSMITH // Commented out until it's added to the map index
prt_in,61,54,3 duplicate(ShadowBlacksmith) Shadow Blacksmith#itemmall 4_F_JOB_BLACKSMITH
//prt_in,61,54,3 duplicate(ShadowBlacksmith) Shadow Blacksmith#itemmall 4_F_JOB_BLACKSMITH
itemmall,31,76,3 duplicate(ShadowBlacksmith) Shadow Blacksmith#itemmall 4_F_JOB_BLACKSMITH

View File

@@ -184,11 +184,11 @@ gl_step,0,0 monster Mimic 1191,6,5000
//==================================================
// gl_cas02_ - Nightmare Mode 2f
//==================================================
gl_cas02_,0,0 monster Evil Druid (Nightmare) 2480,4,0,0,0
gl_cas02_,0,0 monster Chimera (Nightmare) 2485,1,0,0,0
gl_cas02_,0,0 monster Mimic (Nightmare) 2479,19,0,0,0
gl_cas02_,0,0 monster Rideword (Nightmare) 2478,10,0,0,0
gl_cas02_,0,0 monster Wanderer (Nightmare) 2477,60,0,0,0
gl_cas02_,0,0 monster Evil Druid (Nightmare) 2480,4,5000
gl_cas02_,0,0 monster Chimera (Nightmare) 2485,1,5000
gl_cas02_,0,0 monster Mimic (Nightmare) 2479,19,5000
gl_cas02_,0,0 monster Rideword (Nightmare) 2478,10,5000
gl_cas02_,0,0 monster Wanderer (Nightmare) 2477,60,5000
gl_cas02_,0,0 monster Mysteltainn 1203,1,7200000,3600000
gl_cas02_,0,0 monster Alice 1275,1,5000
gl_cas02_,102,180 monster Whisper 1185,1,1800000,900000
@@ -197,8 +197,8 @@ gl_cas02_,0,0 monster Baphomet (Nightmare) 2483,1,7200000,0,0
//==================================================
// gl_chyard_ - Nightmare Mode Churchyard
//==================================================
gl_chyard_,0,0 monster Wraith Dead (Nightmare) 2481,91,0,0,0
gl_chyard_,0,0 monster Wraith Dead 1291,31,0,0,0
gl_chyard_,0,0 monster Wraith Dead (Nightmare) 2481,91,5000
gl_chyard_,0,0 monster Wraith Dead 1291,31,5000
gl_chyard_,0,0 monster Evil Druid (Nightmare) 2480,22,60000,0,0
gl_chyard_,0,0 monster Mimic (Nightmare) 2479,34,60000,0,0
gl_chyard_,0,0,0,0 boss_monster Dark Lord 1272,1,3600000,600000,1

View File

@@ -22,3 +22,10 @@ sp_rudus3,0,0 monster Mutant Dolor 20362,60,5000
sp_rudus3,0,0 monster Mutant Plaga 20360,53,5000
sp_rudus3,0,0 monster Mutant Venenum 20364,65,5000
sp_rudus3,0,0 monster Mutant Twin Caput 20366,65,5000
sp_rudus4 monster Giant Caput GIANT_CAPUT,75
sp_rudus4 monster Dolorian DOLORIAN,75
sp_rudus4 monster Deadre DEADRE,75
sp_rudus4 monster Venedi VENEDI,75
sp_rudus4 monster Plagarion PLAGARION,75
sp_rudus4 boss_monster R001-Bestia R001_BESTIA,1,21600000,600000,0

View File

@@ -10,28 +10,28 @@
//============================================================
// ver_eju
ver_eju,0,0,0,0 monster Recon Robot 3154,50,0,0,0
ver_eju,0,0,0,0 monster Excavator Robot 3153,10,0,0,0
ver_eju,0,0,0,0 monster Recon Robot 3154,50,5000
ver_eju,0,0,0,0 monster Excavator Robot 3153,10,5000
// ver_tunn
ver_tunn,0,0,0,0 monster Recon Robot 3154,5,0,0,0
ver_tunn,0,0,0,0 monster Recon Robot 3154,5,30000
// verus01
verus01,0,0,0,0 monster Green Cenere 3247,50,0,0,0
verus01,0,0,0,0 monster Explorer Robot Turbo 3249,25,0,0,0
verus01,0,0,0,0 monster Repair Robot Turbo 3248,25,0,0,0
verus01,0,0,0,0 monster Green Cenere 3247,50,5000
verus01,0,0,0,0 monster Explorer Robot Turbo 3249,25,5000
verus01,0,0,0,0 monster Repair Robot Turbo 3248,25,5000
// verus02
verus02,0,0,0,0 monster Repair Robot Turbo 3248,50,0,0,0
verus02,0,0,0,0 monster Explorer Robot Turbo 3249,50,0,0,0
verus02,0,0,0,0 monster Repair Robot Turbo 3248,50,5000
verus02,0,0,0,0 monster Explorer Robot Turbo 3249,50,5000
// verus03
verus03,0,0,0,0 monster Illegal Promotion 3159,40,0,0,0
verus03,0,0,0,0 monster Explorer Robot 3156,50,0,0,0
verus03,0,0,0,0 monster Repair Robot 3155,50,0,0,0
verus03,0,0,0,0 monster Ruin Grace Believer 3158,10,0,0,0
verus03,0,0,0,0 monster Illegal Promotion 3159,40,5000
verus03,0,0,0,0 monster Explorer Robot 3156,50,5000
verus03,0,0,0,0 monster Repair Robot 3155,50,5000
verus03,0,0,0,0 monster Ruin Grace Believer 3158,10,5000
// un_bunker
un_bunker,0,0,0,0 monster Thief Bug 1051,6,0,0,0
un_bunker,0,0,0,0 monster Smelly Ghoul 3255,68,0,0,0
un_bunker,0,0,0,0 monster Smelly Zombie 3256,80,0,0,0
un_bunker,0,0,0,0 monster Machine Component 3250,28,0,0,0
un_bunker,0,0,0,0 monster DR815 3252,14,0,0,0
un_bunker,0,0,0,0 monster GC109 3251,10,0,0,0
un_bunker,0,0,0,0 monster Black Mushroom 1084,1,0,0,0
un_bunker,0,0,0,0 monster Chonchon 1011,2,0,0,0
un_bunker,0,0,0,0 monster Thief Bug 1051,6,5000
un_bunker,0,0,0,0 monster Smelly Ghoul 3255,68,5000
un_bunker,0,0,0,0 monster Smelly Zombie 3256,80,5000
un_bunker,0,0,0,0 monster Machine Component 3250,28,5000
un_bunker,0,0,0,0 monster DR815 3252,14,5000
un_bunker,0,0,0,0 monster GC109 3251,10,5000
un_bunker,0,0,0,0 monster Black Mushroom 1084,1,5000
un_bunker,0,0,0,0 monster Chonchon 1011,2,5000

View File

@@ -13,9 +13,11 @@
//===== Additional Comments: =================================
//= 1.0 First version, currently useless/disabled.
//= 1.1 Implemented the 'mergeitem' script command. [Cydh]
//= 1.2 Updated and moved to Cash Mall [Lemongrass]
//============================================================
prontera,146,95,3 script Mergician#pron 64,{
//prontera,146,95,3 script Mergician#pron 1_M_WIZARD,{
itemmall,35,75,3 script Mergician#mall 1_M_WIZARD,{
if (checkweight(1301,1) == 0) {
mes "- Wait a second !! -";
mes "- You are carrying too many items -";
@@ -28,8 +30,8 @@ prontera,146,95,3 script Mergician#pron 64,{
mes "Do you believe in the miracle of Merge god?? If so, repeat my spell loudly as I pronounce it!!!";
mes "Merge Merge, Merrrrge!!!";
next;
switch(select("What is the miracle of Merge?:Merrrrge!!!!:Abandon...")) {
case 1:
switch(select("Merrrrge!!!!:What is the miracle of Merge?:Abandon...")) {
case 2:
mes "[Mergician]";
mes "There is an order which rules the world and keeps the world to go well.";
next;
@@ -47,7 +49,7 @@ prontera,146,95,3 script Mergician#pron 64,{
mes "Believe in Mergism. That is the truth.";
mes "Then I can help you be happy and content.";
close;
case 2:
case 1:
mes "[Mergician]";
mes "This is the total holy ritual to pray to the Great God, Merge! and I am borrowing the power for a while!!";
next;

View File

@@ -0,0 +1,480 @@
//===== rAthena Script =======================================
//= New dungeons
//===== Description: =========================================
//= [Walkthrough Conversion]
//===== Changelog: ===========================================
//= 1.0 Added sp_rudus4 quests. [Capuche]
//============================================================
// sp_rudus4
pub_cat,94,43,5 script Yulma#rudus4 4_F_ANYA,{
if (BaseLevel < 200) {
mes "[Yulma]";
mes "Uh... who are you?";
mes "Sorry, I'm not good at remembering people's faces! But I think you are not good enough to ask about my work here.";
next;
mes " - This is a quest that can be performed at level 200 or higher - ";
close;
}
switch( isbegin_quest(16521) ) {
case 0:
emotion ET_SMILE;
mes "[Yulma]";
mes "Oh, " + strcharinfo(0) + ". Are you here for a drink?";
mes "I just had a business, and it went well.";
next;
select( "What is it for?" );
mes "[Yulma]";
mes "You know that Secret Wing and our rebellion have been tracking the traces of Illusion's illegal experiments, right?";
next;
mes "[Yulma]";
mes "In the meantime, I found a way to the 4th floor of Rudus.";
next;
switch( select( "Well, I know.", "Where was Rudus?" ) ) {
case 1:
emotion ET_DELIGHT;
mes "[Yulma]";
mes "Hehe, it's good to have a good conversation with " + strcharinfo(0) + ".";
break;
case 2:
emotion ET_SURPRISE;
mes "[Yulma]";
mes "What, how many times did you forget?";
mes "It was the place where Illusion abandoned the failed works that were created after the experiment.";
next;
mes "[Yulma]";
mes "Remember Morning? Where the little boy stays.";
mes "He is on the first floor, and Rudus itself exists on the second and third floors.";
break;
}
next;
mes "[Yulma]";
mes "By the way, the 4th floor of Rudus is quite amazing...";
mes "Somehow, among the test subjects abandoned in Rudus, only particularly strong ones seem to be gathered.";
next;
mes "[Yulma]";
mes "Researchers of the Secret Wing say that after fierce competition among the subjects, the strongest subjects seem to have settled there.";
next;
mes "[Yulma]";
mes "Well, actually, I'm not sure how complicated it is!";
mes "It seems that the Secret Wing researchers need to study the entities there.";
next;
mes "[Yulma]";
mes "So I was looking for someone to help me.";
mes "To be precise you, " + strcharinfo(0) + "!";
next;
mes "[Yulma]";
mes "Do you need a job? I know everything~";
mes "If you have an idea, go to the 3rd floor of Rudus.";
next;
mes "[Yulma]";
mes "<NAVI>[Pion]<INFO>sp_rudus3,380,42,0,101,0</INFO></NAVI> is in control of the path leading down to the fourth floor.";
mes "Go and tell him I sent you, and find out if it's worth it to come!";
setquest 16521;
close2;
navigateto("sp_rudus3",380,42);
end;
case 1:
mes "[Yulma]";
mes "Do you need a job? I know everything~";
mes "If you have an idea, go to the 3rd floor of Rudus.";
next;
mes "[Yulma]";
mes "<NAVI>[Pion]<INFO>sp_rudus3,380,42,0,101,0</INFO></NAVI> is in control of the path leading down to the fourth floor.";
mes "Go and tell him I sent you, and find out if it's worth it to come!";
close;
case 2:
break;
}
if (isbegin_quest(16522) == 1) {
mes "[Yulma]";
mes "Oh, you went down to the 4th floor of Rudus. How was it?";
mes "Is Pian doing well? Did the subjects feel a bit worthy of a fight?";
next;
mes "[Yulma]";
mes "Then help me study the people from the Secret Wing.";
mes "I was looking for someone to hunt them, because I was not enough to catch and research monsters myself.";
next;
select( "Ask if I can just hunt" );
emotion ET_KEK;
mes "[Yulma]";
mes "Oh, I almost forgot.";
mes "If you attach this chip somewhere on your body and hunt them, researchers can receive data.";
next;
mes "[Yulma]";
mes "New material, eco-friendly, non-toxic, safe material, so you don't have to worry about it.";
mes "Where would you like to hang it?";
next;
select( "Earlobe", "Back neck", "Back of hand", "Forehead" );
mes "[Yulma]";
mes "Okay, I'll attach it well so it doesn't bother you.";
mes "Okay, that's it then...";
completequest 16522;
next;
}
mes "[Yulma]";
mes "Please take good care of me today!";
mes "So, what kind of research would you like to help with today?";
next;
switch( select("Abyssal Solitude", "Transformation and Evolution", "Data Backup", "Don't help" ) ) {
case 1:
switch( checkquest(16523,PLAYTIME) ) {
case -1:
break;
case 0:
case 1:
mes "[Yulma]";
mes "Secret Wing researchers are resting.";
mes "So, " + strcharinfo(0) + ", how about coming back after a little rest?";
next;
mes "[Yulma]";
mes "The 4th floor of Rudus is not a comfortable place to go in and out easily.";
mes "Let's get some rest and work fully prepared!";
close;
case 2:
erasequest 16523;
break;
}
switch( checkquest(16524,HUNTING) ) {
case -1:
mes "[Yulma]";
mes "A place where only strong individuals survive and bite weaker ones...";
mes "Like a deep, dark pit of solitude.";
next;
emotion ET_SWEAT;
mes "[Yulma]";
mes "Well, I don't know about that!";
mes "My job is to deliver the requests of researchers.";
next;
mes "[Yulma]";
mes "Researchers want to know how the subjects of Rudus differ from those distributed on the 4th floor.";
next;
emotion ET_PROFUSELY_SWAT;
mes "[Yulma]";
mes "How much more has it lost it's original form, and whether it has changed itself after the experiment.";
mes "<FONT SIZE = 9>Um... these researchers look a little dangerous too? I think that's how all researchers are, to a person like me.</FONT>";
next;
mes "[Yulma]";
mes "Anyway, you want to collect <FONT COLOR = 0000CD>Dolorian, Plagarion, and Deadre</FONT> data.";
mes "What if we hunt 10 individuals each?";
next;
if (select( "I'll come hunting", "I refuse" ) == 2) {
mes "[Yulma]";
mes "We're already comrades on the same boat~?";
mes "Isn't that right, comrade? Think again!";
close;
}
mes "[Yulma]";
mes "Okay, if you go hunting and from hunting, data will be gathered.";
mes "And my allowance will be accumulating!";
setquest 16524;
close;
case 0:
case 1:
mes "[Yulma]";
mes "Secret Wing researchers want to collect <FONT COLOR = 0000CD>Dolorian, Plagarion, and Deadre</FONT> data.";
mes "What if we hunt 10 individuals each?";
close;
case 2:
mes "[Yulma]";
mes "Today's hunting seems to be successful!";
mes "How did you know, " + strcharinfo(0) + ", the chip I put on you worked today.";
next;
emotion ET_DELIGHT;
mes "[Yulma]";
mes "I see it every time, but every time it's amazing, how the chip works.";
mes "Well, I should pay you for the work you did today.";
next;
mes "[Yulma]";
mes "Here you are!";
mes "Then since you've finished your work, take a good rest. Please take care of me tomorrow as well~";
erasequest 16524;
setquest 16523;
getexp 15915940,11141160; // TODO: the amount has been changed with the monster update
close;
}
end;
case 2:
switch( checkquest(16525,PLAYTIME) ) {
case -1:
break;
case 0:
case 1:
mes "[Yulma]";
mes "Secret Wing researchers left work already.";
mes "So, " + strcharinfo(0) + ", how about coming back after a little rest?";
next;
mes "[Yulma]";
mes "The 4th floor of Rudus is not a comfortable place to go in and out easily.";
mes "You too, get a good rest, and let's work fully prepared!";
close;
case 2:
erasequest 16525;
break;
}
switch( checkquest(16526,HUNTING) ) {
case -1:
mes "[Yulma]";
mes "The 4th-floor entities Giant Caput and Venedi are greatly altered from the other-floor entities";
mes "to become gigantic, or to harbor more venom...";
next;
emotion ET_PROFUSELY_SWAT;
mes "[Yulma]";
mes "Researchers seem to be very interested in these guys.";
mes "That's why I ask you to hunt them.";
mes "<FONT SIZE = 9>Um...why don't we do it? There must be something complicated at the upper level. I don't know.</FONT>";
next;
mes "[Yulma]";
mes "Can you hunt 15 <FONT COLOR = 0000CD>Giant Caput and Venedi</FONT> each?";
mes "Data will be collected automatically, so you just need to focus on hunting.";
next;
if (select( "I'll hunt them", "I refuse" ) == 2) {
mes "[Yulma]";
mes "We're already comrades on the same boat~?";
mes "Isn't that right, comrade? Think again!";
close;
}
mes "[Yulma]";
mes "Okay, go and hunt hard!";
mes "My bonus depends on your performance!";
setquest 16526;
close;
case 0:
case 1:
mes "[Yulma]";
mes "Can you hunt 15 <FONT COLOR = 0000CD>Giant Caput and Venedi</FONT> each?";
mes "Data will be collected automatically, so you just need to focus on hunting.";
close;
case 2:
mes "[Yulma]";
mes "Have you been well? You came back from hunting safely.";
mes "Please tell me that the researchers worked hard today.";
next;
mes "[Yulma]";
mes "Looks like good data has been gathered.";
mes "Then I should pay you for the work you did today.";
next;
mes "[Yulma]";
mes "Here you are!";
mes "You worked hard today, so get a good rest and come back. Let's work hard tomorrow!";
erasequest 16526;
setquest 16525;
getexp 15176970,11001900; // TODO: the amount has been changed with the monster update
close;
}
end;
case 3:
switch( checkquest(16527,PLAYTIME) ) {
case -1:
break;
case 0:
case 1:
mes "[Yulma]";
mes "The researcher said he's withdrawn now. Chip maintenance is enough once a day!";
mes "So, " + strcharinfo(0) + ", how about coming back after a little rest?";
next;
mes "[Yulma]";
mes "The 4th floor of Rudus is not a comfortable place to go in and out easily.";
mes "Let's get some rest and work fully prepared!";
close;
case 2:
erasequest 16527;
break;
}
switch( isbegin_quest(16528) ) {
case 0:
mes "[Yulma]";
mes "Oh, by the way, are the chips sticking well?";
mes "It doesn't last that long...";
next;
mes "[Yulma]";
mes "And I have to back up and format the data I have collected so that I can receive new data, but I don't have the talent to do that...";
next;
mes "[Yulma]";
mes "I'll introduce you to a researcher who is currently in the field, would you like to go directly?";
mes "He is probably disguised to observe monsters, but I'll give you the location, so go check it out!";
next;
if (select( "Look for him", "Don't look for him" ) == 2) {
mes "[Yulma]";
mes "Isn't it frustrating to only work with me?";
mes "It wouldn't be a bad idea to meet the researchers working in the field...";
close;
}
mes "[Yulma]";
mes "Yeah! Isn't it frustrating to only meet with me to get work delivered?";
next;
mes "[Yulma]";
mes "I'm on my way to see him, so if you have any questions, you can ask him directly!";
mes "I heard that <NAVI>[Researcher]<INFO>sp_rudus4,192,204,0,101,0</INFO></NAVI> mostly burrows around the center of the 4th floor of Rudus.";
setquest 16528;
close;
case 1:
mes "[Yulma]";
mes "I'm on my way to meet the Secret Wing researcher, so if you have any questions, you can ask him directly!";
mes "I heard that <NAVI>[Researcher]<INFO>sp_rudus4,192,204,0,101,0</INFO></NAVI> mostly burrows around the center of the 4th floor of Rudus.";
close;
case 2:
mes "[Yulma]";
mes "Have you been there? Did you talk a bit?";
mes "Is the researcher hiding well?";
next;
mes "[Yulma]";
mes "He's known for hiding very well, even though he doesn't have the skills to hide.";
mes "That's why you're out in the field.";
next;
mes "[Yulma]";
mes "Because this is also a job... Since I safely replaced him, the superiors asked me to take care of the allowance.";
next;
mes "[Yulma]";
mes "Well, it's good that you came back to me too!";
mes "Then have a good day and see you tomorrow!";
erasequest 16528;
erasequest 16540;
setquest 16527;
getexp 15000000,11000000;
close;
}
end;
case 4:
mes "[Yulma]";
mes "Eh, won't you?";
mes "I was eagerly waiting for " + strcharinfo(0) + "!";
close;
}
end;
OnInit:
questinfo( QTYPE_QUEST2, QMARK_YELLOW, "checkquest(16524,HUNTING) == 2" );
questinfo( QTYPE_QUEST2, QMARK_YELLOW, "checkquest(16526,HUNTING) == 2" );
questinfo( QTYPE_QUEST2, QMARK_YELLOW, "isbegin_quest(16528) == 2" );
questinfo( QTYPE_DAILYQUEST, QMARK_YELLOW, "checkquest(16523,PLAYTIME) == 2" );
questinfo( QTYPE_DAILYQUEST, QMARK_YELLOW, "checkquest(16525,PLAYTIME) == 2" );
questinfo( QTYPE_DAILYQUEST, QMARK_YELLOW, "checkquest(16527,PLAYTIME) == 2" );
questinfo( QTYPE_DAILYQUEST, QMARK_YELLOW, "BaseLevel >= 200 && (checkquest(16524,HUNTING) == -1 && checkquest(16523,PLAYTIME) == -1)" );
questinfo( QTYPE_DAILYQUEST, QMARK_YELLOW, "BaseLevel >= 200 && (checkquest(16526,HUNTING) == -1 && checkquest(16525,PLAYTIME) == -1)" );
questinfo( QTYPE_DAILYQUEST, QMARK_YELLOW, "BaseLevel >= 200 && (isbegin_quest(16528) == 0 && checkquest(16527,PLAYTIME) == -1)" );
end;
}
sp_rudus3,380,42,3 script Pion#rudus4 4_M_REBELLION3,{
switch( isbegin_quest(16521) ) {
case 0:
emotion ET_SLEEPY;
mes "[Pion]";
mes "Zzz... Whoa!";
mes "Excuse me, sir! No more work!";
next;
mes "[Pion]";
mes "Seup, Ha-am... Down this slope is an access control area.";
mes "People are not allowed to enter.";
next;
select("I'm not an ordinary person." );
mes "[Pion]";
mes "Yes? Ah... ah no! " + strcharinfo(0) + " !";
mes "That... Still, I can't let you in on my own.";
close;
case 1:
emotion ET_SLEEPY;
mes "[Pion]";
mes "Zzz... Whoa!";
mes "Excuse me! No more work!";
next;
mes "[Pion]";
mes "Oops... ah, this is definitely not saliva";
mes "It is a drop of sweat that shines with passion and effort.";
next;
mes "[Pion]";
mes "Hmm, hmmm. The entrance down this slope is now restricted...";
mes "What's going on?";
next;
if (select( "I want to go to the 4th floor of Rudus.", "Point out the working attitude." ) == 2) {
mes "[Pion]";
mes "Oh, there's a problem with your working attitude?";
mes "Sa, some people might sleep!!";
next;
mes "[Pion]";
mes "I only slept a little!";
mes "Really!";
close;
}
mes "[Pion]";
mes "Fourth floor? I'm in control right there...";
mes "Ah, did you come to see Yulma from Bullet Meow?";
next;
mes "[Pion]";
mes "Then you should pass it.";
mes "If you want to look at the specimens on the 4th floor and help with a research request, go back to <NAVI>[Yulma]<INFO>pub_cat,94,43,0,101,0</INFO></NAVI> and ask.";
next;
mes "[Pion]";
mes "I'll move you to the 4th floor.";
close2;
completequest 16521;
setquest 16522;
warp "sp_rudus4",370,156;
end;
case 2:
break;
}
emotion ET_SLEEPY;
mes "[Pion]";
mes "Zzz... Huh! Shi, excuse me!";
mes "Are you sure you want to go down to the 4th floor of Rudus?";
next;
if (select( "Move", "Do not move" ) == 2) {
mes "[Pion]";
mes "I see. Ha-am....";
close;
}
mes "[Pion]";
mes "I'll move you. Take care!";
close2;
warp "sp_rudus4",370,156;
end;
OnInit:
questinfo( QTYPE_DAILYQUEST, QMARK_YELLOW, "isbegin_quest(16521) == 1" );
end;
}
sp_rudus4,192,204,3 script Secret Wing Researcher#rudu 4_SOIL,{
mes "[Secret Wing Researcher]";
mes "Good. Field work.";
mes "You have to watch a lot of monsters.";
next;
emotion ET_HUK;
mes "[Secret Wing Researcher]";
mes "...huh!";
mes "How did you recognize me?";
next;
if (isbegin_quest(16528) == 1) {
mes "[Secret Wing Researcher]";
mes "Oh, look again, " + strcharinfo(0) + ".";
mes "I got a call. Are you here to renew the chip?";
next;
mes "[Secret Wing Researcher]";
mes "Let's see... Let's get some chips.";
mes "Hmmmm... Connect with my machine... Empty data...";
next;
emotion ET_BEST;
mes "[Secret Wing Researcher]";
mes "Okay, that's it! The data is clean and very nice. I'll paste it again.";
next;
mes "[Secret Wing Researcher]";
mes "Because this is also a job, <NAVI>[Yulma]<INFO>pub_cat,94,43,0,101,0</INFO></NAVI> will give you a small allowance when you return.";
mes "I am always indebted to you. Good job!";
completequest 16528;
setquest 16540;
close;
}
emotion ET_KEK;
mes "[Secret Wing Researcher]";
mes "Evil! If you pretend to know, monsters will come!";
mes "Go away!";
close;
OnInit:
questinfo( QTYPE_DAILYQUEST, QMARK_YELLOW, "isbegin_quest(16528) == 1" );
end;
}

View File

@@ -115,6 +115,7 @@ npc: npc/re/merchants/bio4_reward.txt
//npc: npc/re/merchants/blessed_refiner.txt
//npc: npc/re/merchants/card_exchange.txt
npc: npc/re/merchants/card_separation.txt
npc: npc/re/merchants/cashmall.txt
npc: npc/re/merchants/catalog.txt
npc: npc/re/merchants/clothing_buff_removal.txt
npc: npc/re/merchants/coin_exchange.txt
@@ -154,7 +155,7 @@ npc: npc/re/merchants/shops.txt
npc: npc/re/merchants/Slot_Move_Card_Sales.txt
npc: npc/re/merchants/socket_enchant2.txt
//npc: npc/re/merchants/ticket_refiner.txt
//npc: npc/re/merchants/enchan_upg.txt
npc: npc/re/merchants/enchan_upg.txt
//npc: npc/re/merchants/cash_trader-idRO.txt
npc: npc/re/merchants/te_merchant.txt
npc: npc/re/merchants/shadow_refiner.txt
@@ -227,6 +228,7 @@ npc: npc/re/quests/quests_aldebaran.txt
npc: npc/re/quests/quests_brasilis.txt
npc: npc/re/quests/quests_dewata.txt
npc: npc/re/quests/quests_dicastes.txt
npc: npc/re/quests/quests_dungeons_200.txt
npc: npc/re/quests/quests_eclage.txt
npc: npc/re/quests/quests_glastheim.txt
npc: npc/re/quests/quests_izlude.txt

View File

@@ -9,3 +9,5 @@ sp_rudus,180,258,0 warp rudus1_to_rudus2 1,1,sp_rudus2,185,258
sp_rudus2,180,258,0 warp rudus2_to_rudus1 1,1,sp_rudus,185,258
sp_rudus2,359,206,0 warp rudus2_to_rudus3 1,1,sp_rudus3,366,207
sp_rudus3,371,207,0 warp rudus3_to_rudus2 1,1,sp_rudus2,355,206
sp_rudus4,380,156,0 warp2 #b_hw1 2,2,sp_rudus3,375,45

View File

@@ -155,7 +155,6 @@ npc: npc/merchants/wander_pet_food.txt
// - Cash Shop
// See file before enabling, as you may wish to change the
// point value of items to suit your own needs.
//npc: npc/merchants/cash_hair.txt
//npc: npc/merchants/cash_trader.txt
npc: npc/merchants/cashheadgear_dye.txt

View File

@@ -6,23 +6,21 @@ The files in this directory are basic SQL table building scripts. The contained
### New Install
---
For a new install, the following needs to be imported into the 'ragnarok' schema:
For a new install, the following needs to be imported into the main schema:
Note: The schema name is defined in `conf/inter_athena.conf::map_server_db`.
* main.sql - Contains tables for normal server usage.
* web.sql - Contains tables for the web service
* roulette_default_data.sql - Contains data for the client's roulette game.
For a new install, the following needs to be imported into the 'log' schema:
For a new install, the following can be imported into the main schema but is highly suggested to be imported into a separate schema for logs:
Note: The schema name is defined in `conf/inter_athena.conf::log_db_db`.
* logs.sql - Contains tables for logging of server events.
If your server is setup to read SQL database data, import the following:
If your server is setup to read SQL database data, import the following into the main schema:
Note: If `conf/inter_athena.conf::use_sql_db` is set to yes continue with these imports else these can be skipped. Not all files have to be imported, only the ones that apply to the same mode as the server being ran.
* item_cash_db.sql - Used for client's cash shop.
* item_cash_db2.sql - Used for client's cash shop (import).
* item_db.sql - Contains __pre-renewal__ item data table structure.
* item_db_equip.sql - Contains __pre-renewal__ equipment item data.
* item_db_etc.sql - Contains __pre-renewal__ etcetera item data.
@@ -44,8 +42,8 @@ Note: If `conf/inter_athena.conf::use_sql_db` is set to yes continue with these
### Updates
---
Over the course of time new features and optimizations will take place. This may require SQL changes to happen. In the `upgrades` folder will be upgrade files with an attached date.
These imports only have to executed if an update has occurred after the initial installation. Many times a SQL error will be displayed on the server console stating the format differs from what is required.
Over the course of time new features and optimizations will take place. This may require SQL changes to happen. In the `upgrades` folder will be SQL files with an attached date.
These only have to executed one time if an update has occurred after the initial installation. It's possible to see when an update may be required when a SQL error will be displayed on the server console stating the format differs from what is required.
### Compatibility
---
@@ -76,4 +74,4 @@ To run these queries the user requires the [FILE](https://dev.mysql.com/doc/refm
### Notes
---
The web-server must be able to read the `login` and `guild` tables from the `login-server` and `char-server`, respectively.
The `web-server` must be able to read the `login` and `guild` tables from the `login-server` and `char-server`, respectively.

View File

@@ -1,7 +0,0 @@
DROP TABLE IF EXISTS `item_cash_db`;
CREATE TABLE `item_cash_db` (
`tab` smallint(6) NOT NULL,
`item_id` int(10) unsigned NOT NULL,
`price` mediumint(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`tab`,`item_id`)
) ENGINE=MyISAM;

View File

@@ -1,7 +0,0 @@
DROP TABLE IF EXISTS `item_cash_db2`;
CREATE TABLE `item_cash_db2` (
`tab` smallint(6) NOT NULL,
`item_id` int(10) unsigned NOT NULL,
`price` mediumint(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`tab`,`item_id`)
) ENGINE=MyISAM;

View File

@@ -5641,11 +5641,11 @@ REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_sha
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_armor`,`equip_level_min`,`refineable`,`script`) VALUES (24344,'S_Blitz_Armor','Blitz Shadow Armor','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\nbonus bDef,25+5*(.@r/2);\nif (.@r >= 7) {\n bonus bAspd,1;\n if (.@r >= 9) {\n bonus bDelayrate,-1;\n }\n}');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_shield`,`equip_level_min`,`refineable`,`script`) VALUES (24345,'S_Tempest_Shield','Tempest Shadow Shield','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\nbonus2 bIgnoreMdefClassRate,Class_Normal,5+(.@r/2);');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_shoes`,`equip_level_min`,`refineable`,`script`) VALUES (24346,'S_Tempest_Shoes','Tempest Shadow Shoes','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\nbonus2 bIgnoreMdefClassRate,Class_Normal,5+(.@r/2);');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_armor`,`equip_level_min`,`refineable`,`script`) VALUES (24347,'S_Magic_Executioner_Holy_Water_Armor','Magic Executioner Holy Water Shadow Armor','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\n.@val = 5 + (.@r/2);\nbonus2 bIgnoreMdefRaceRate,RC_DemiHuman,.@val;\nbonus2 bIgnoreMdefRaceRate,RC_Undead,.@val;');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_armor`,`equip_level_min`,`refineable`,`script`) VALUES (24348,'S_Magic_Exorcist_Corrupted_Armor','Magic Exorcist Corrupted Shadow Armor','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\n.@val = 5 + (.@r/2);\nbonus2 bIgnoreMdefRaceRate,RC_Demon,.@val;\nbonus2 bIgnoreMdefRaceRate,RC_Angel,.@val;');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_armor`,`equip_level_min`,`refineable`,`script`) VALUES (24349,'S_Magic_Vibration_Dragon_Killer_Armor','Magic Vibration Dragon Killer Shadow Armor','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\n.@val = 5 + (.@r/2);\nbonus2 bIgnoreMdefRaceRate,RC_Formless,.@val;\nbonus2 bIgnoreMdefRaceRate,RC_Dragon,.@val;');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_armor`,`equip_level_min`,`refineable`,`script`) VALUES (24350,'S_Magic_Scissor_Hunting_Armor','Magic Scissor Hunting Shadow Armor','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\n.@val = 5 + (.@r/2);\nbonus2 bIgnoreMdefRaceRate,RC_Plant,.@val;\nbonus2 bIgnoreMdefRaceRate,RC_Brute,.@val;\nbonus2 bIgnoreMdefRaceRate,RC_Player_Doram,.@val;');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_armor`,`equip_level_min`,`refineable`,`script`) VALUES (24351,'S_Magic_Fishing_Insect_Net_Armor','Magic Fishing Insect Net Shadow Armor','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\n.@val = 5 + (.@r/2);\nbonus2 bIgnoreMdefRaceRate,RC_Fish,.@val;\nbonus2 bIgnoreMdefRaceRate,RC_Insect,.@val;');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_armor`,`equip_level_min`,`refineable`,`script`) VALUES (24347,'S_M_ExeHoly_Armor','Magic Executioner Holy Water Shadow Armor','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\n.@val = 5 + (.@r/2);\nbonus2 bIgnoreMdefRaceRate,RC_DemiHuman,.@val;\nbonus2 bIgnoreMdefRaceRate,RC_Undead,.@val;');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_armor`,`equip_level_min`,`refineable`,`script`) VALUES (24348,'S_M_ExoCorrupt_Armor','Magic Exorcist Corrupted Shadow Armor','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\n.@val = 5 + (.@r/2);\nbonus2 bIgnoreMdefRaceRate,RC_Demon,.@val;\nbonus2 bIgnoreMdefRaceRate,RC_Angel,.@val;');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_armor`,`equip_level_min`,`refineable`,`script`) VALUES (24349,'S_M_DragonVib_Armor','Magic Vibration Dragon Killer Shadow Armor','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\n.@val = 5 + (.@r/2);\nbonus2 bIgnoreMdefRaceRate,RC_Formless,.@val;\nbonus2 bIgnoreMdefRaceRate,RC_Dragon,.@val;');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_armor`,`equip_level_min`,`refineable`,`script`) VALUES (24350,'S_M_SciHunting_Armor','Magic Scissor Hunting Shadow Armor','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\n.@val = 5 + (.@r/2);\nbonus2 bIgnoreMdefRaceRate,RC_Plant,.@val;\nbonus2 bIgnoreMdefRaceRate,RC_Brute,.@val;\nbonus2 bIgnoreMdefRaceRate,RC_Player_Doram,.@val;');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_armor`,`equip_level_min`,`refineable`,`script`) VALUES (24351,'S_M_FishInsect_Armor','Magic Fishing Insect Net Shadow Armor','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\n.@val = 5 + (.@r/2);\nbonus2 bIgnoreMdefRaceRate,RC_Fish,.@val;\nbonus2 bIgnoreMdefRaceRate,RC_Insect,.@val;');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_armor`,`equip_level_min`,`refineable`,`script`) VALUES (24352,'S_Plasterer\'s_Armor_II','Plasterer\'s Shadow Armor II','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\nbonus bDef,1;\nbonus2 bResEff,Eff_Stone,100*.@r;');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_shoes`,`equip_level_min`,`refineable`,`script`) VALUES (24353,'S_Insomniac_Shoes_II','Insomniac Shadow Shoes II','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\nbonus bDef,1;\nbonus2 bResEff,Eff_Sleep,100*.@r;');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_armor`,`equip_level_min`,`refineable`,`script`) VALUES (24354,'S_Peerless_Armor_II','Peerless Shadow Armor II','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\nbonus bDef,1;\nbonus2 bResEff,Eff_Silence,100*.@r;');
@@ -5669,11 +5669,11 @@ REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_sha
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_left_accessory`,`equip_level_min`,`refineable`,`script`) VALUES (24372,'S_Mortal_Blow_Pendant','Mortal Blow Shadow Pendant','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\nif (.@r >= 9) {\n .@val = 3;\n} else if (.@r >= 7) {\n .@val = 2;\n}\nelse {\n .@val = 1;\n}\nbonus bCritAtkRate,.@val;');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_shoes`,`equip_level_min`,`refineable`,`script`) VALUES (24373,'S_Penetration_Shoes','Penetration Shadow Shoes','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\nbonus2 bIgnoreDefClassRate,Class_Normal,5+(.@r/2);');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_shield`,`equip_level_min`,`refineable`,`script`) VALUES (24374,'S_Penetration_Shield','Penetration Shadow Shield','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\nbonus2 bIgnoreDefClassRate,Class_Normal,5+(.@r/2);');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_armor`,`equip_level_min`,`refineable`,`script`) VALUES (24375,'S_Executioner_Holy_Water_Armor','Executioner Holy Water Shadow Armor','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\n.@val = 5 + (.@r/2);\nbonus2 bIgnoreDefRaceRate,RC_DemiHuman,.@val;\nbonus2 bIgnoreDefRaceRate,RC_Undead,.@val;');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_armor`,`equip_level_min`,`refineable`,`script`) VALUES (24376,'S_Exorcist_Corrupted_Armor','Exorcist Corrupted Shadow Armor','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\n.@val = 5 + (.@r/2);\nbonus2 bIgnoreDefRaceRate,RC_Demon,.@val;\nbonus2 bIgnoreDefRaceRate,RC_Angel,.@val;');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_armor`,`equip_level_min`,`refineable`,`script`) VALUES (24377,'S_Vibration_Dragon_Killer_Armor','Vibration Dragon Killer Shadow Armor','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\n.@val = 5 + (.@r/2);\nbonus2 bIgnoreDefRaceRate,RC_Formless,.@val;\nbonus2 bIgnoreDefRaceRate,RC_Dragon,.@val;');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_armor`,`equip_level_min`,`refineable`,`script`) VALUES (24378,'S_Scissor_Hunting_Armor','Scissor Hunting Shadow Armor','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\n.@val = 5 + (.@r/2);\nbonus2 bIgnoreDefRaceRate,RC_Plant,.@val;\nbonus2 bIgnoreDefRaceRate,RC_Brute,.@val;');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_armor`,`equip_level_min`,`refineable`,`script`) VALUES (24379,'S_Fishing_Insect_Net_Armor','Fishing Insect Net Shadow Armor','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\n.@val = 5 + (.@r/2);\nbonus2 bIgnoreDefRaceRate,RC_Fish,.@val;\nbonus2 bIgnoreDefRaceRate,RC_Insect,.@val;');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_armor`,`equip_level_min`,`refineable`,`script`) VALUES (24375,'S_ExeHoly_Armor','Executioner Holy Water Shadow Armor','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\n.@val = 5 + (.@r/2);\nbonus2 bIgnoreDefRaceRate,RC_DemiHuman,.@val;\nbonus2 bIgnoreDefRaceRate,RC_Undead,.@val;');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_armor`,`equip_level_min`,`refineable`,`script`) VALUES (24376,'S_ExoCorrupt_Armor','Exorcist Corrupted Shadow Armor','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\n.@val = 5 + (.@r/2);\nbonus2 bIgnoreDefRaceRate,RC_Demon,.@val;\nbonus2 bIgnoreDefRaceRate,RC_Angel,.@val;');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_armor`,`equip_level_min`,`refineable`,`script`) VALUES (24377,'S_DragonVib_Armor','Vibration Dragon Killer Shadow Armor','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\n.@val = 5 + (.@r/2);\nbonus2 bIgnoreDefRaceRate,RC_Formless,.@val;\nbonus2 bIgnoreDefRaceRate,RC_Dragon,.@val;');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_armor`,`equip_level_min`,`refineable`,`script`) VALUES (24378,'S_SciHunting_Armor','Scissor Hunting Shadow Armor','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\n.@val = 5 + (.@r/2);\nbonus2 bIgnoreDefRaceRate,RC_Plant,.@val;\nbonus2 bIgnoreDefRaceRate,RC_Brute,.@val;');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_armor`,`equip_level_min`,`refineable`,`script`) VALUES (24379,'S_FishInsect_Armor','Fishing Insect Net Shadow Armor','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\n.@val = 5 + (.@r/2);\nbonus2 bIgnoreDefRaceRate,RC_Fish,.@val;\nbonus2 bIgnoreDefRaceRate,RC_Insect,.@val;');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_weapon`,`equip_level_min`,`refineable`,`script`) VALUES (24380,'Sentimental_Weapone_S','Sentimental Shadow Weapon','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bBaseAtk,.@r;\nbonus bMatk,.@r;\nbonus bMaxSP,10+((.@r/2)*15);');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_right_accessory`,`equip_level_min`,`refineable`,`script`) VALUES (24381,'Sentimental_Earring_S','Sentimental Shadow Earring','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\nbonus bMaxSP,(.@r/2)*5;\nbonus bMaxSPrate,1;\nbonus bBaseAtk,5;');
REPLACE INTO `item_db_re` (`id`,`name_aegis`,`name_english`,`type`,`location_shadow_left_accessory`,`equip_level_min`,`refineable`,`script`) VALUES (24382,'Sentimental_Pendant_S','Sentimental Shadow Pendant','Shadowgear',true,1,true,'.@r = getrefine();\nbonus bMaxHP,.@r*10;\nbonus bSPrecovRate,2+.@r/3;\nbonus bBaseAtk,5;');

View File

@@ -940,6 +940,8 @@ CREATE TABLE IF NOT EXISTS `sc_data` (
`char_id` int(11) unsigned NOT NULL,
`type` smallint(11) unsigned NOT NULL,
`tick` bigint(20) NOT NULL,
`tick_total` bigint(20) NOT NULL,
`tick_time` bigint(20) NOT NULL,
`val1` int(11) NOT NULL default '0',
`val2` int(11) NOT NULL default '0',
`val3` int(11) NOT NULL default '0',
@@ -973,6 +975,27 @@ CREATE TABLE IF NOT EXISTS `party` (
PRIMARY KEY (`party_id`)
) ENGINE=MyISAM;
--
-- Table structure for table `party_bookings`
--
CREATE TABLE IF NOT EXISTS `party_bookings` (
`world_name` varchar(32) NOT NULL,
`account_id` int(11) unsigned NOT NULL,
`char_id` int(11) unsigned NOT NULL,
`char_name` varchar(23) NOT NULL,
`purpose` smallint(5) unsigned NOT NULL DEFAULT '0',
`assist` tinyint(3) unsigned NOT NULL DEFAULT '0',
`damagedealer` tinyint(3) unsigned NOT NULL DEFAULT '0',
`healer` tinyint(3) unsigned NOT NULL DEFAULT '0',
`tanker` tinyint(3) unsigned NOT NULL DEFAULT '0',
`minimum_level` smallint(5) unsigned NOT NULL,
`maximum_level` smallint(5) unsigned NOT NULL,
`comment` varchar(255) NOT NULL DEFAULT '',
`created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`world_name`, `account_id`, `char_id`)
) ENGINE=MyISAM;
--
-- Table structure for table `pet`
--

View File

@@ -0,0 +1,5 @@
ALTER TABLE `sc_data` ADD COLUMN `tick_total` BIGINT(20) NOT NULL AFTER `tick`;
UPDATE `sc_data` SET `tick_total` = `tick`;
ALTER TABLE `sc_data` ADD COLUMN `tick_time` BIGINT(20) NOT NULL AFTER `tick_total`;
UPDATE `sc_data` SET `tick_time` = `tick`;

View File

@@ -0,0 +1,823 @@
/**
ATTENTION!!!
Please make sure to create a backup of your live data before running this update.
This update is rather complicated and although I have tried my best I cannot guarantee that I did not make any mistake. [Lemongrass]
We would also advise you to check the data in the temporary table after the insert statement and before the update statements.
You could do so by running
select * from `tmp_randomoptionfix` where `new_index` <> `old_index`;
to see where changes happen and options will be moved.
For executing this update your user needs create table and drop table permissions. Either run the update with another user [admin or root for example] or give your database user these permissions temporarily.
Do not forget to remove these permissions again, as they are usually not necessary and it is rather dangerous, if someone gets access to your database user.
Additionally if you have more than one storage table (see conf/inter_server.yml) make sure to also update those tables (see instructions at the bottom of this script).
Comment the line below to really run the script, this is a safeguard that you confirm you have read and understood what was written above.
**/
cancel;
-- Create a temporary table to store the data for the update
create table `tmp_randomoptionfix` (
`id` int(11) unsigned NOT NULL,
`new_index` smallint(5) NOT NULL,
`old_index` smallint(5) NOT NULL,
`option_id` smallint(5) NOT NULL,
`option_val` smallint(5) NOT NULL,
`option_parm` tinyint(3) NOT NULL,
PRIMARY KEY ( `id`, `old_index` )
);
-- Create auction data
insert into `tmp_randomoptionfix` ( `id`, `new_index`, `old_index`, `option_id`, `option_val`, `option_parm` )
select
`id`,
row_number() over( partition by `id` order by `old_index` asc ) - 1 as `new_index`,
`old_index`,
`option_id`,
`option_val`,
`option_parm`
from (
select * from (
select
`auction_id` as `id`,
0 as `old_index`,
`option_id0` as `option_id`,
`option_val0` as `option_val`,
`option_parm0` as `option_parm`
from `auction`
where `option_id0` <> 0
union
select
`auction_id` as `id`,
1 as `old_index`,
`option_id1` as `option_id`,
`option_val1` as `option_val`,
`option_parm1` as `option_parm`
from `auction`
where `option_id1` <> 0
union
select
`auction_id` as `id`,
2 as `old_index`,
`option_id2` as `option_id`,
`option_val2` as `option_val`,
`option_parm2` as `option_parm`
from `auction`
where `option_id2` <> 0
union
select
`auction_id` as `id`,
3 as `old_index`,
`option_id3` as `option_id`,
`option_val3` as `option_val`,
`option_parm3` as `option_parm`
from `auction`
where `option_id3` <> 0
union
select
`auction_id` as `id`,
4 as `old_index`,
`option_id4` as `option_id`,
`option_val4` as `option_val`,
`option_parm4` as `option_parm`
from `auction`
where `option_id4` <> 0
) t2
order by `id`, `old_index`
) t ;
-- Fix option 0
update `auction`
left join `tmp_randomoptionfix`
on `auction`.`auction_id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 0
set
`option_id0` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val0` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm0` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 1
update `auction`
left join `tmp_randomoptionfix`
on `auction`.`auction_id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 1
set
`option_id1` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val1` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm1` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 2
update `auction`
left join `tmp_randomoptionfix`
on `auction`.`auction_id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 2
set
`option_id2` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val2` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm2` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 3
update `auction`
left join `tmp_randomoptionfix`
on `auction`.`auction_id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 3
set
`option_id3` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val3` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm3` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 4
update `auction`
left join `tmp_randomoptionfix`
on `auction`.`auction_id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 4
set
`option_id4` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val4` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm4` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Delete the data to have a clean table for the next run
delete from `tmp_randomoptionfix`;
-- Create cart_inventory data
insert into `tmp_randomoptionfix` ( `id`, `new_index`, `old_index`, `option_id`, `option_val`, `option_parm` )
select
`id`,
row_number() over( partition by `id` order by `old_index` asc ) - 1 as `new_index`,
`old_index`,
`option_id`,
`option_val`,
`option_parm`
from (
select * from (
select
`id`,
0 as `old_index`,
`option_id0` as `option_id`,
`option_val0` as `option_val`,
`option_parm0` as `option_parm`
from `cart_inventory`
where `option_id0` <> 0
union
select
`id`,
1 as `old_index`,
`option_id1` as `option_id`,
`option_val1` as `option_val`,
`option_parm1` as `option_parm`
from `cart_inventory`
where `option_id1` <> 0
union
select
`id`,
2 as `old_index`,
`option_id2` as `option_id`,
`option_val2` as `option_val`,
`option_parm2` as `option_parm`
from `cart_inventory`
where `option_id2` <> 0
union
select
`id`,
3 as `old_index`,
`option_id3` as `option_id`,
`option_val3` as `option_val`,
`option_parm3` as `option_parm`
from `cart_inventory`
where `option_id3` <> 0
union
select
`id`,
4 as `old_index`,
`option_id4` as `option_id`,
`option_val4` as `option_val`,
`option_parm4` as `option_parm`
from `cart_inventory`
where `option_id4` <> 0
) t2
order by `id`, `old_index`
) t ;
-- Fix option 0
update `cart_inventory`
left join `tmp_randomoptionfix`
on `cart_inventory`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 0
set
`option_id0` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val0` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm0` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 1
update `cart_inventory`
left join `tmp_randomoptionfix`
on `cart_inventory`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 1
set
`option_id1` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val1` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm1` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 2
update `cart_inventory`
left join `tmp_randomoptionfix`
on `cart_inventory`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 2
set
`option_id2` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val2` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm2` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 3
update `cart_inventory`
left join `tmp_randomoptionfix`
on `cart_inventory`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 3
set
`option_id3` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val3` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm3` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 4
update `cart_inventory`
left join `tmp_randomoptionfix`
on `cart_inventory`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 4
set
`option_id4` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val4` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm4` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Delete the data to have a clean table for the next run
delete from `tmp_randomoptionfix`;
-- Create guild_storage data
insert into `tmp_randomoptionfix` ( `id`, `new_index`, `old_index`, `option_id`, `option_val`, `option_parm` )
select
`id`,
row_number() over( partition by `id` order by `old_index` asc ) - 1 as `new_index`,
`old_index`,
`option_id`,
`option_val`,
`option_parm`
from (
select * from (
select
`id`,
0 as `old_index`,
`option_id0` as `option_id`,
`option_val0` as `option_val`,
`option_parm0` as `option_parm`
from `guild_storage`
where `option_id0` <> 0
union
select
`id`,
1 as `old_index`,
`option_id1` as `option_id`,
`option_val1` as `option_val`,
`option_parm1` as `option_parm`
from `guild_storage`
where `option_id1` <> 0
union
select
`id`,
2 as `old_index`,
`option_id2` as `option_id`,
`option_val2` as `option_val`,
`option_parm2` as `option_parm`
from `guild_storage`
where `option_id2` <> 0
union
select
`id`,
3 as `old_index`,
`option_id3` as `option_id`,
`option_val3` as `option_val`,
`option_parm3` as `option_parm`
from `guild_storage`
where `option_id3` <> 0
union
select
`id`,
4 as `old_index`,
`option_id4` as `option_id`,
`option_val4` as `option_val`,
`option_parm4` as `option_parm`
from `guild_storage`
where `option_id4` <> 0
) t2
order by `id`, `old_index`
) t ;
-- Fix option 0
update `guild_storage`
left join `tmp_randomoptionfix`
on `guild_storage`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 0
set
`option_id0` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val0` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm0` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 1
update `guild_storage`
left join `tmp_randomoptionfix`
on `guild_storage`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 1
set
`option_id1` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val1` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm1` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 2
update `guild_storage`
left join `tmp_randomoptionfix`
on `guild_storage`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 2
set
`option_id2` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val2` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm2` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 3
update `guild_storage`
left join `tmp_randomoptionfix`
on `guild_storage`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 3
set
`option_id3` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val3` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm3` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 4
update `guild_storage`
left join `tmp_randomoptionfix`
on `guild_storage`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 4
set
`option_id4` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val4` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm4` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Delete the data to have a clean table for the next run
delete from `tmp_randomoptionfix`;
-- Create inventory data
insert into `tmp_randomoptionfix` ( `id`, `new_index`, `old_index`, `option_id`, `option_val`, `option_parm` )
select
`id`,
row_number() over( partition by `id` order by `old_index` asc ) - 1 as `new_index`,
`old_index`,
`option_id`,
`option_val`,
`option_parm`
from (
select * from (
select
`id`,
0 as `old_index`,
`option_id0` as `option_id`,
`option_val0` as `option_val`,
`option_parm0` as `option_parm`
from `inventory`
where `option_id0` <> 0
union
select
`id`,
1 as `old_index`,
`option_id1` as `option_id`,
`option_val1` as `option_val`,
`option_parm1` as `option_parm`
from `inventory`
where `option_id1` <> 0
union
select
`id`,
2 as `old_index`,
`option_id2` as `option_id`,
`option_val2` as `option_val`,
`option_parm2` as `option_parm`
from `inventory`
where `option_id2` <> 0
union
select
`id`,
3 as `old_index`,
`option_id3` as `option_id`,
`option_val3` as `option_val`,
`option_parm3` as `option_parm`
from `inventory`
where `option_id3` <> 0
union
select
`id`,
4 as `old_index`,
`option_id4` as `option_id`,
`option_val4` as `option_val`,
`option_parm4` as `option_parm`
from `inventory`
where `option_id4` <> 0
) t2
order by `id`, `old_index`
) t ;
-- Fix option 0
update `inventory`
left join `tmp_randomoptionfix`
on `inventory`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 0
set
`option_id0` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val0` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm0` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 1
update `inventory`
left join `tmp_randomoptionfix`
on `inventory`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 1
set
`option_id1` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val1` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm1` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 2
update `inventory`
left join `tmp_randomoptionfix`
on `inventory`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 2
set
`option_id2` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val2` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm2` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 3
update `inventory`
left join `tmp_randomoptionfix`
on `inventory`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 3
set
`option_id3` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val3` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm3` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 4
update `inventory`
left join `tmp_randomoptionfix`
on `inventory`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 4
set
`option_id4` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val4` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm4` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Delete the data to have a clean table for the next run
delete from `tmp_randomoptionfix`;
-- Create mail_attachments data
insert into `tmp_randomoptionfix` ( `id`, `new_index`, `old_index`, `option_id`, `option_val`, `option_parm` )
select
`id`,
row_number() over( partition by `id` order by `old_index` asc ) - 1 as `new_index`,
`old_index`,
`option_id`,
`option_val`,
`option_parm`
from (
select * from (
select
`id`,
0 as `old_index`,
`option_id0` as `option_id`,
`option_val0` as `option_val`,
`option_parm0` as `option_parm`
from `mail_attachments`
where `option_id0` <> 0
union
select
`id`,
1 as `old_index`,
`option_id1` as `option_id`,
`option_val1` as `option_val`,
`option_parm1` as `option_parm`
from `mail_attachments`
where `option_id1` <> 0
union
select
`id`,
2 as `old_index`,
`option_id2` as `option_id`,
`option_val2` as `option_val`,
`option_parm2` as `option_parm`
from `mail_attachments`
where `option_id2` <> 0
union
select
`id`,
3 as `old_index`,
`option_id3` as `option_id`,
`option_val3` as `option_val`,
`option_parm3` as `option_parm`
from `mail_attachments`
where `option_id3` <> 0
union
select
`id`,
4 as `old_index`,
`option_id4` as `option_id`,
`option_val4` as `option_val`,
`option_parm4` as `option_parm`
from `mail_attachments`
where `option_id4` <> 0
) t2
order by `id`, `old_index`
) t ;
-- Fix option 0
update `mail_attachments`
left join `tmp_randomoptionfix`
on `mail_attachments`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 0
set
`option_id0` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val0` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm0` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 1
update `mail_attachments`
left join `tmp_randomoptionfix`
on `mail_attachments`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 1
set
`option_id1` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val1` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm1` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 2
update `mail_attachments`
left join `tmp_randomoptionfix`
on `mail_attachments`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 2
set
`option_id2` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val2` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm2` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 3
update `mail_attachments`
left join `tmp_randomoptionfix`
on `mail_attachments`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 3
set
`option_id3` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val3` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm3` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 4
update `mail_attachments`
left join `tmp_randomoptionfix`
on `mail_attachments`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 4
set
`option_id4` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val4` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm4` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Delete the data to have a clean table for the next run
delete from `tmp_randomoptionfix`;
-- Create storage data
insert into `tmp_randomoptionfix` ( `id`, `new_index`, `old_index`, `option_id`, `option_val`, `option_parm` )
select
`id`,
row_number() over( partition by `id` order by `old_index` asc ) - 1 as `new_index`,
`old_index`,
`option_id`,
`option_val`,
`option_parm`
from (
select * from (
select
`id`,
0 as `old_index`,
`option_id0` as `option_id`,
`option_val0` as `option_val`,
`option_parm0` as `option_parm`
from `storage`
where `option_id0` <> 0
union
select
`id`,
1 as `old_index`,
`option_id1` as `option_id`,
`option_val1` as `option_val`,
`option_parm1` as `option_parm`
from `storage`
where `option_id1` <> 0
union
select
`id`,
2 as `old_index`,
`option_id2` as `option_id`,
`option_val2` as `option_val`,
`option_parm2` as `option_parm`
from `storage`
where `option_id2` <> 0
union
select
`id`,
3 as `old_index`,
`option_id3` as `option_id`,
`option_val3` as `option_val`,
`option_parm3` as `option_parm`
from `storage`
where `option_id3` <> 0
union
select
`id`,
4 as `old_index`,
`option_id4` as `option_id`,
`option_val4` as `option_val`,
`option_parm4` as `option_parm`
from `storage`
where `option_id4` <> 0
) t2
order by `id`, `old_index`
) t ;
-- Fix option 0
update `storage`
left join `tmp_randomoptionfix`
on `storage`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 0
set
`option_id0` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val0` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm0` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 1
update `storage`
left join `tmp_randomoptionfix`
on `storage`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 1
set
`option_id1` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val1` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm1` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 2
update `storage`
left join `tmp_randomoptionfix`
on `storage`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 2
set
`option_id2` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val2` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm2` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 3
update `storage`
left join `tmp_randomoptionfix`
on `storage`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 3
set
`option_id3` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val3` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm3` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 4
update `storage`
left join `tmp_randomoptionfix`
on `storage`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 4
set
`option_id4` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val4` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm4` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Delete the data to have a clean table for the next run
delete from `tmp_randomoptionfix`;
-- Repeat this for any other storage tables that you have created (for example VIP)
-- To do this copy paste the code below and replace ${other_storage} with the name of your table
/**
-- Create ${other_storage} data
insert into `tmp_randomoptionfix` ( `id`, `new_index`, `old_index`, `option_id`, `option_val`, `option_parm` )
select
`id`,
row_number() over( partition by `id` order by `old_index` asc ) - 1 as `new_index`,
`old_index`,
`option_id`,
`option_val`,
`option_parm`
from (
select * from (
select
`id`,
0 as `old_index`,
`option_id0` as `option_id`,
`option_val0` as `option_val`,
`option_parm0` as `option_parm`
from `${other_storage}`
where `option_id0` <> 0
union
select
`id`,
1 as `old_index`,
`option_id1` as `option_id`,
`option_val1` as `option_val`,
`option_parm1` as `option_parm`
from `${other_storage}`
where `option_id1` <> 0
union
select
`id`,
2 as `old_index`,
`option_id2` as `option_id`,
`option_val2` as `option_val`,
`option_parm2` as `option_parm`
from `${other_storage}`
where `option_id2` <> 0
union
select
`id`,
3 as `old_index`,
`option_id3` as `option_id`,
`option_val3` as `option_val`,
`option_parm3` as `option_parm`
from `${other_storage}`
where `option_id3` <> 0
union
select
`id`,
4 as `old_index`,
`option_id4` as `option_id`,
`option_val4` as `option_val`,
`option_parm4` as `option_parm`
from `${other_storage}`
where `option_id4` <> 0
) t2
order by `id`, `old_index`
) t ;
-- Fix option 0
update `${other_storage}`
left join `tmp_randomoptionfix`
on `${other_storage}`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 0
set
`option_id0` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val0` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm0` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 1
update `${other_storage}`
left join `tmp_randomoptionfix`
on `${other_storage}`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 1
set
`option_id1` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val1` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm1` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 2
update `${other_storage}`
left join `tmp_randomoptionfix`
on `${other_storage}`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 2
set
`option_id2` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val2` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm2` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 3
update `${other_storage}`
left join `tmp_randomoptionfix`
on `${other_storage}`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 3
set
`option_id3` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val3` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm3` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Fix option 4
update `${other_storage}`
left join `tmp_randomoptionfix`
on `${other_storage}`.`id` = `tmp_randomoptionfix`.`id` and `tmp_randomoptionfix`.`new_index` = 4
set
`option_id4` = coalesce( `tmp_randomoptionfix`.`option_id`, 0 ),
`option_val4` = coalesce( `tmp_randomoptionfix`.`option_val`, 0 ),
`option_parm4` = coalesce( `tmp_randomoptionfix`.`option_parm`, 0 )
;
-- Delete the data to have a clean table for the next run
delete from `tmp_randomoptionfix`;
**/
drop table `tmp_randomoptionfix`;

View File

@@ -0,0 +1,20 @@
--
-- Table structure for table `party_bookings`
--
CREATE TABLE IF NOT EXISTS `party_bookings` (
`world_name` varchar(32) NOT NULL,
`account_id` int(11) unsigned NOT NULL,
`char_id` int(11) unsigned NOT NULL,
`char_name` varchar(23) NOT NULL,
`purpose` smallint(5) unsigned NOT NULL DEFAULT '0',
`assist` tinyint(3) unsigned NOT NULL DEFAULT '0',
`damagedealer` tinyint(3) unsigned NOT NULL DEFAULT '0',
`healer` tinyint(3) unsigned NOT NULL DEFAULT '0',
`tanker` tinyint(3) unsigned NOT NULL DEFAULT '0',
`minimum_level` smallint(5) unsigned NOT NULL,
`maximum_level` smallint(5) unsigned NOT NULL,
`comment` varchar(255) NOT NULL DEFAULT '',
`created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`world_name`, `account_id`, `char_id`)
) ENGINE=MyISAM;

View File

@@ -110,6 +110,7 @@
<PreprocessorDefinitions>$(DefineConstants);WIN32;FD_SETSIZE=4096;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_WINSOCK_DEPRECATED_NO_WARNINGS;LIBCONFIG_STATIC;YY_USE_CONST;_DEBUG;_CONSOLE;_LIB;_ITERATOR_DEBUG_LEVEL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalIncludeDirectories>$(SolutionDir)3rdparty\rapidyaml\src;$(SolutionDir)3rdparty\rapidyaml\ext\c4core\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -229,4 +230,4 @@
<Copy SourceFiles="$(SolutionDir)tools\charserv.bat" DestinationFolder="$(SolutionDir)" ContinueOnError="true" Condition="!Exists('$(SolutionDir)charserv.bat')" />
<Copy SourceFiles="$(SolutionDir)tools\runserver.bat" DestinationFolder="$(SolutionDir)" ContinueOnError="true" Condition="!Exists('$(SolutionDir)runserver.bat')" />
</Target>
</Project>
</Project>

View File

@@ -4,6 +4,9 @@
#pragma warning(disable:4800)
#include "char.hpp"
#include <memory>
#include <unordered_map>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -22,6 +25,7 @@
#include "../common/socket.hpp"
#include "../common/strlib.hpp"
#include "../common/timer.hpp"
#include "../common/utilities.hpp"
#include "char_clif.hpp"
#include "char_cnslif.hpp"
@@ -37,6 +41,9 @@
#include "int_storage.hpp"
#include "packets.hpp"
using namespace rathena;
using namespace rathena::server_character;
//definition of exported var declared in header
int login_fd=-1; //login file descriptor
int char_fd=-1; //char file descriptor
@@ -68,31 +75,31 @@ struct s_subnet {
} subnet[16];
int subnet_count = 0;
DBMap* auth_db; // uint32 account_id -> struct auth_node*
DBMap* online_char_db; // uint32 account_id -> struct online_char_data*
DBMap* char_db_; // uint32 char_id -> struct mmo_charstatus*
DBMap* char_get_authdb() { return auth_db; }
DBMap* char_get_onlinedb() { return online_char_db; }
DBMap* char_get_chardb() { return char_db_; }
// uint32 account_id -> struct auth_node*
std::unordered_map<uint32, std::shared_ptr<struct auth_node>> auth_db;
// uint32 account_id -> struct online_char_data*
std::unordered_map<uint32, std::shared_ptr<struct online_char_data>> online_char_db;
// uint32 char_id -> struct mmo_charstatus*
std::unordered_map<uint32, std::shared_ptr<struct mmo_charstatus>> char_db;
std::unordered_map<uint32, std::shared_ptr<struct auth_node>>& char_get_authdb() { return auth_db; }
std::unordered_map<uint32, std::shared_ptr<struct online_char_data>>& char_get_onlinedb() { return online_char_db; }
std::unordered_map<uint32, std::shared_ptr<struct mmo_charstatus>>& char_get_chardb() { return char_db; }
/**
* @see DBCreateData
*/
DBData char_create_online_data(DBKey key, va_list args){
struct online_char_data* character;
CREATE(character, struct online_char_data, 1);
character->account_id = key.i;
character->char_id = -1;
character->server = -1;
character->fd = -1;
character->waiting_disconnect = INVALID_TIMER;
return db_ptr2data(character);
online_char_data::online_char_data( uint32 account_id ){
this->account_id = account_id;
this->char_id = -1;
this->server = -1;
this->fd = -1;
this->waiting_disconnect = INVALID_TIMER;
}
void char_set_charselect(uint32 account_id) {
struct online_char_data* character;
std::shared_ptr<struct online_char_data> character = util::umap_find( char_get_onlinedb(), account_id );
character = (struct online_char_data*)idb_ensure(online_char_db, account_id, char_create_online_data);
if( character == nullptr ){
character = std::make_shared<struct online_char_data>( account_id );
char_get_onlinedb()[account_id] = character;
}
if( character->server > -1 )
if( map_server[character->server].users > 0 ) // Prevent this value from going negative.
@@ -111,20 +118,27 @@ void char_set_charselect(uint32 account_id) {
}
void char_set_char_online(int map_id, uint32 char_id, uint32 account_id) {
struct online_char_data* character;
struct mmo_charstatus *cp;
//Update DB
if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='1', `last_login`=NOW() WHERE `char_id`='%d' LIMIT 1", schema_config.char_db, char_id) )
Sql_ShowDebug(sql_handle);
//Check to see for online conflicts
character = (struct online_char_data*)idb_ensure(online_char_db, account_id, char_create_online_data);
if( character->char_id != -1 && character->server > -1 && character->server != map_id )
{
ShowNotice("set_char_online: Character %d:%d marked in map server %d, but map server %d claims to have (%d:%d) online!\n",
character->account_id, character->char_id, character->server, map_id, account_id, char_id);
mapif_disconnectplayer(map_server[character->server].fd, character->account_id, character->char_id, 2);
std::shared_ptr<struct online_char_data> character = util::umap_find( char_get_onlinedb(), account_id );
if( character != nullptr ){
if( character->char_id != -1 && character->server > -1 && character->server != map_id ){
ShowNotice("set_char_online: Character %d:%d marked in map server %d, but map server %d claims to have (%d:%d) online!\n",
character->account_id, character->char_id, character->server, map_id, account_id, char_id);
mapif_disconnectplayer(map_server[character->server].fd, character->account_id, character->char_id, 2);
}
// Get rid of disconnect timer
if( character->waiting_disconnect != INVALID_TIMER ){
delete_timer( character->waiting_disconnect, char_chardb_waiting_disconnect );
character->waiting_disconnect = INVALID_TIMER;
}
}else{
character = std::make_shared<struct online_char_data>( account_id );
}
//Update state data
@@ -134,14 +148,9 @@ void char_set_char_online(int map_id, uint32 char_id, uint32 account_id) {
if( character->server > -1 )
map_server[character->server].users++;
//Get rid of disconnect timer
if(character->waiting_disconnect != INVALID_TIMER) {
delete_timer(character->waiting_disconnect, char_chardb_waiting_disconnect);
character->waiting_disconnect = INVALID_TIMER;
}
//Set char online in guild cache. If char is in memory, use the guild id on it, otherwise seek it.
cp = (struct mmo_charstatus*)idb_get(char_db_,char_id);
std::shared_ptr<struct mmo_charstatus> cp = util::umap_find( char_get_chardb(), char_id );
inter_guild_CharOnline(char_id, cp?cp->guild_id:-1);
//Notify login server
@@ -149,8 +158,6 @@ void char_set_char_online(int map_id, uint32 char_id, uint32 account_id) {
}
void char_set_char_offline(uint32 char_id, uint32 account_id){
struct online_char_data* character;
if ( char_id == -1 )
{
if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='0' WHERE `account_id`='%d'", schema_config.char_db, account_id) )
@@ -158,17 +165,20 @@ void char_set_char_offline(uint32 char_id, uint32 account_id){
}
else
{
struct mmo_charstatus* cp = (struct mmo_charstatus*)idb_get(char_db_,char_id);
std::shared_ptr<struct mmo_charstatus> cp = util::umap_find( char_get_chardb(), char_id );
inter_guild_CharOffline(char_id, cp?cp->guild_id:-1);
if (cp)
idb_remove(char_db_,char_id);
char_get_chardb().erase( char_id );
if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='0' WHERE `char_id`='%d' LIMIT 1", schema_config.char_db, char_id) )
Sql_ShowDebug(sql_handle);
}
if ((character = (struct online_char_data*)idb_get(online_char_db, account_id)) != NULL)
{ //We don't free yet to avoid aCalloc/aFree spamming during char change. [Skotlex]
std::shared_ptr<struct online_char_data> character = util::umap_find( char_get_onlinedb(), account_id );
// We don't free yet to avoid aCalloc/aFree spamming during char change. [Skotlex]
if( character != nullptr ){
if( character->server > -1 )
if( map_server[character->server].users > 0 ) // Prevent this value from going negative.
map_server[character->server].users--;
@@ -195,12 +205,7 @@ void char_set_char_offline(uint32 char_id, uint32 account_id){
}
}
/**
* @see DBApply
*/
int char_db_setoffline(DBKey key, DBData *data, va_list ap) {
struct online_char_data* character = (struct online_char_data*)db_data2ptr(data);
int server = va_arg(ap, int);
void char_db_setoffline( std::shared_ptr<struct online_char_data> character, int server ){
if (server == -1) {
character->char_id = -1;
character->server = -1;
@@ -210,28 +215,17 @@ int char_db_setoffline(DBKey key, DBData *data, va_list ap) {
}
} else if (character->server == server)
character->server = -2; //In some map server that we aren't connected to.
return 0;
}
/**
* @see DBApply
*/
int char_db_kickoffline(DBKey key, DBData *data, va_list ap){
struct online_char_data* character = (struct online_char_data*)db_data2ptr(data);
int server_id = va_arg(ap, int);
void char_db_kickoffline( std::shared_ptr<struct online_char_data> character, int server_id ){
if (server_id > -1 && character->server != server_id)
return 0;
return;
//Kick out any connected characters, and set them offline as appropriate.
if (character->server > -1)
mapif_disconnectplayer(map_server[character->server].fd, character->account_id, character->char_id, 1);
else if (character->waiting_disconnect == INVALID_TIMER)
char_set_char_offline(character->char_id, character->account_id);
else
return 0; // fail
return 1;
}
void char_set_all_offline(int id){
@@ -239,7 +233,10 @@ void char_set_all_offline(int id){
ShowNotice("Sending all users offline.\n");
else
ShowNotice("Sending users of map-server %d offline.\n",id);
online_char_db->foreach(online_char_db,char_db_kickoffline,id);
for( const auto& pair : char_get_onlinedb() ){
char_db_kickoffline( pair.second, id );
}
if (id >= 0 || !chlogif_isconnected())
return;
@@ -255,28 +252,23 @@ void char_set_all_offline_sql(void){
Sql_ShowDebug(sql_handle);
}
/**
* @see DBCreateData
*/
DBData char_create_charstatus(DBKey key, va_list args) {
struct mmo_charstatus *cp;
cp = (struct mmo_charstatus *) aCalloc(1,sizeof(struct mmo_charstatus));
cp->char_id = key.i;
return db_ptr2data(cp);
}
int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){
int i = 0;
int count = 0;
int diff = 0;
char save_status[128]; //For displaying save information. [Skotlex]
struct mmo_charstatus *cp;
int errors = 0; //If there are any errors while saving, "cp" will not be updated at the end.
StringBuf buf;
if (char_id!=p->char_id) return 0;
cp = (struct mmo_charstatus *)idb_ensure(char_db_, char_id, char_create_charstatus);
std::shared_ptr<struct mmo_charstatus> cp = util::umap_find( char_get_chardb(), char_id );
if( cp == nullptr ){
cp = std::make_shared<struct mmo_charstatus>();
cp->char_id = char_id;
char_get_chardb()[cp->char_id] = cp;
}
StringBuf_Init(&buf);
memset(save_status, 0, sizeof(save_status));
@@ -524,8 +516,11 @@ int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){
StringBuf_Destroy(&buf);
if (save_status[0]!='\0' && charserv_config.save_log)
ShowInfo("Saved char %d - %s:%s.\n", char_id, p->name, save_status);
if (!errors)
memcpy(cp, p, sizeof(struct mmo_charstatus));
if( !errors ){
memcpy( cp.get(), p, sizeof( struct mmo_charstatus ) );
}
return 0;
}
@@ -1033,7 +1028,6 @@ int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf, uint8* coun
//=====================================================================================================
int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_everything) {
int i;
struct mmo_charstatus* cp;
SqlStmt* stmt;
char last_map[MAP_NAME_LENGTH_EXT];
char save_map[MAP_NAME_LENGTH_EXT];
@@ -1271,16 +1265,22 @@ int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_ev
ShowInfo("Loaded char (%d - %s): %s\n", char_id, p->name, StringBuf_Value(&msg_buf)); //ok. all data load successfully!
SqlStmt_Free(stmt);
cp = (struct mmo_charstatus *)idb_ensure(char_db_, char_id, char_create_charstatus);
memcpy(cp, p, sizeof(struct mmo_charstatus));
std::shared_ptr<struct mmo_charstatus> cp = util::umap_find( char_get_chardb(), char_id );
if( cp == nullptr ){
cp = std::make_shared<struct mmo_charstatus>();
cp->char_id = char_id;
char_get_chardb()[cp->char_id] = cp;
}
memcpy( cp.get(), p, sizeof( struct mmo_charstatus ) );
StringBuf_Destroy(&msg_buf);
return 1;
}
//==========================================================================================================
int char_mmo_sql_init(void) {
char_db_= idb_alloc(DB_OPT_RELEASE_DATA);
ShowStatus("Characters per Account: '%d'.\n", charserv_config.char_config.char_per_account);
//the 'set offline' part is now in check_login_conn ...
@@ -1998,10 +1998,10 @@ void char_set_session_flag_(int account_id, int val, bool set) {
}
void char_auth_ok(int fd, struct char_session_data *sd) {
struct online_char_data* character;
std::shared_ptr<struct online_char_data> character = util::umap_find( char_get_onlinedb(), sd->account_id );
if( (character = (struct online_char_data*)idb_get(online_char_db, sd->account_id)) != NULL )
{ // check if character is not online already. [Skotlex]
// Check if character is not online already. [Skotlex]
if( character != nullptr ){
if (character->server > -1)
{ //Character already online. KICK KICK KICK
mapif_disconnectplayer(map_server[character->server].fd, character->account_id, character->char_id, 2);
@@ -2206,33 +2206,38 @@ void char_pincode_decrypt( uint32 userSeed, char* pin ){
//replies/disconnect the player we tried to kick. [Skotlex]
//------------------------------------------------
TIMER_FUNC(char_chardb_waiting_disconnect){
struct online_char_data* character;
if ((character = (struct online_char_data*)idb_get(online_char_db, id)) != NULL && character->waiting_disconnect == tid)
{ //Mark it offline due to timeout.
std::shared_ptr<struct online_char_data> character = util::umap_find( char_get_onlinedb(), static_cast<uint32>( id ) );
// Mark it offline due to timeout.
if( character != nullptr && character->waiting_disconnect == tid ){
character->waiting_disconnect = INVALID_TIMER;
char_set_char_offline(character->char_id, character->account_id);
}
return 0;
}
/**
* @see DBApply
*/
int char_online_data_cleanup_sub(DBKey key, DBData *data, va_list ap)
{
struct online_char_data *character= (struct online_char_data *)db_data2ptr(data);
if (character->fd != -1)
return 0; //Character still connected
if (character->server == -2) //Unknown server.. set them offline
char_set_char_offline(character->char_id, character->account_id);
if (character->server < 0)
//Free data from players that have not been online for a while.
db_remove(online_char_db, key);
return 0;
}
TIMER_FUNC(char_online_data_cleanup){
online_char_db->foreach(online_char_db, char_online_data_cleanup_sub);
for( auto it = char_get_onlinedb().begin(); it != char_get_onlinedb().end(); ){
std::shared_ptr<struct online_char_data> character = it->second;
// Character still connected
if( character->fd != -1 ){
return 0;
}
// Unknown server - set them offline
if( character->server == -2 ){
char_set_char_offline( character->char_id, character->account_id );
}
// Free data from players that have not been online for a while.
if( character->server < 0 ){
it = char_get_onlinedb().erase( it );
}else{
it++;
}
}
return 0;
}
@@ -2380,7 +2385,7 @@ bool char_checkdb(void){
return false;
}
//checking scdata_db
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`char_id`,`type`,`tick`,`val1`,`val2`,`val3`,`val4`"
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`char_id`,`type`,`tick`,`tick_total`,`tick_time`,`val1`,`val2`,`val3`,`val4`"
" FROM `%s` LIMIT 1;", schema_config.scdata_db) ){
Sql_ShowDebug(sql_handle);
return false;
@@ -2820,6 +2825,8 @@ void char_set_defaults(){
#else
charserv_config.allowed_job_flag = 1;
#endif
charserv_config.clear_parties = 0;
}
/**
@@ -3107,6 +3114,8 @@ bool char_config_read(const char* cfgName, bool normal){
charserv_config.mail_return_empty = config_switch(w2);
} else if (strcmpi(w1, "allowed_job_flag") == 0) {
charserv_config.allowed_job_flag = atoi(w2);
} else if (strcmpi(w1, "clear_parties") == 0) {
charserv_config.clear_parties = config_switch(w2);
} else if (strcmpi(w1, "import") == 0) {
char_config_read(w2, normal);
}
@@ -3142,9 +3151,7 @@ void char_do_final_msg(void){
_do_final_msg(CHAR_MAX_MSG,msg_table);
}
void do_final(void)
{
void CharacterServer::finalize(){
ShowStatus("Terminating...\n");
char_set_all_offline(-1);
@@ -3158,9 +3165,9 @@ void do_final(void)
do_final_chmapif();
do_final_chlogif();
char_db_->destroy(char_db_, NULL);
online_char_db->destroy(online_char_db, NULL);
auth_db->destroy(auth_db, NULL);
char_get_chardb().clear();
char_get_onlinedb().clear();
char_get_authdb().clear();
if( char_fd != -1 )
{
@@ -3174,40 +3181,17 @@ void do_final(void)
ShowStatus("Finished.\n");
}
void set_server_type(void){
SERVER_TYPE = ATHENA_SERVER_CHAR;
}
//------------------------------
// Function called when the server
// has received a crash signal.
//------------------------------
void do_abort(void)
{
}
/// Called when a terminate signal is received.
void do_shutdown(void) {
if( runflag != CHARSERVER_ST_SHUTDOWN )
{
int id;
runflag = CHARSERVER_ST_SHUTDOWN;
ShowStatus("Shutting down...\n");
// TODO proper shutdown procedure; wait for acks?, kick all characters, ... [FlavoJS]
for( id = 0; id < ARRAYLENGTH(map_server); ++id )
chmapif_server_reset(id);
chlogif_check_shutdown();
flush_fifos();
runflag = CORE_ST_STOP;
}
void CharacterServer::handle_shutdown(){
ShowStatus("Shutting down...\n");
// TODO proper shutdown procedure; wait for acks?, kick all characters, ... [FlavoJS]
for( int id = 0; id < ARRAYLENGTH(map_server); ++id )
chmapif_server_reset(id);
flush_fifos();
}
int do_init(int argc, char **argv)
{
bool CharacterServer::initialize( int argc, char *argv[] ){
//Read map indexes
runflag = CHARSERVER_ST_STARTING;
mapindex_init();
// Init default value
@@ -3227,17 +3211,16 @@ int do_init(int argc, char **argv)
char_sql_config_read(SQL_CONF_NAME);
msg_config_read(MSG_CONF_NAME_EN);
// Skip this check if the server is run with run-once flag
if (runflag!=CORE_ST_STOP && strcmp(charserv_config.userid, "s1")==0 && strcmp(charserv_config.passwd, "p1")==0) {
#if !defined(BUILDBOT)
if (strcmp(charserv_config.userid, "s1")==0 && strcmp(charserv_config.passwd, "p1")==0) {
ShowWarning("Using the default user/password s1/p1 is NOT RECOMMENDED.\n");
ShowNotice("Please edit your 'login' table to create a proper inter-server user/password (gender 'S')\n");
ShowNotice("And then change the user/password to use in conf/char_athena.conf (or conf/import/char_conf.txt)\n");
}
#endif
inter_init_sql((argc > 2) ? argv[2] : SQL_CONF_NAME); // inter server configuration
auth_db = idb_alloc(DB_OPT_RELEASE_DATA);
online_char_db = idb_alloc(DB_OPT_RELEASE_DATA);
char_mmo_sql_init();
char_read_fame_list(); //Read fame lists.
@@ -3289,7 +3272,7 @@ int do_init(int argc, char **argv)
//check db tables
if(charserv_config.char_check_db && char_checkdb() == 0){
ShowFatalError("char : A tables is missing in sql-server, please fix it, see (sql-files main.sql for structure) \n");
exit(EXIT_FAILURE);
return false;
}
//Cleaning the tables for NULL entrys @ startup [Sirius]
//Chardb clean
@@ -3308,13 +3291,7 @@ int do_init(int argc, char **argv)
if( (char_fd = make_listen_bind(charserv_config.bind_ip,charserv_config.char_port)) == -1 ) {
ShowFatalError("Failed to bind to port '" CL_WHITE "%d" CL_RESET "'\n",charserv_config.char_port);
exit(EXIT_FAILURE);
}
if( runflag != CORE_ST_STOP )
{
shutdown_callback = do_shutdown;
runflag = CHARSERVER_ST_RUNNING;
return false;
}
do_init_chcnslif();
@@ -3323,5 +3300,9 @@ int do_init(int argc, char **argv)
ShowStatus("The char-server is " CL_GREEN "ready" CL_RESET " (Server is listening on the port %d).\n\n", charserv_config.char_port);
return 0;
return true;
}
int main( int argc, char *argv[] ){
return main_core<CharacterServer>( argc, argv );
}

View File

@@ -4,6 +4,8 @@
#ifndef CHAR_HPP
#define CHAR_HPP
#include <memory>
#include <unordered_map>
#include <vector>
#include "../common/core.hpp" // CORE_ST_LAST
@@ -14,19 +16,31 @@
#include "packets.hpp"
using rathena::server_core::Core;
using rathena::server_core::e_core_type;
namespace rathena{
namespace server_character{
class CharacterServer : public Core{
protected:
bool initialize( int argc, char* argv[] ) override;
void finalize() override;
void handle_shutdown() override;
public:
CharacterServer() : Core( e_core_type::CHARACTER ){
}
};
}
}
extern int login_fd; //login file descriptor
extern int char_fd; //char file descriptor
#define MAX_STARTPOINT 5
#define MAX_STARTITEM 32
enum E_CHARSERVER_ST {
CHARSERVER_ST_RUNNING = CORE_ST_LAST,
CHARSERVER_ST_STARTING,
CHARSERVER_ST_SHUTDOWN,
CHARSERVER_ST_LAST
};
enum e_char_delete {
CHAR_DEL_EMAIL = 1,
CHAR_DEL_BIRTHDATE
@@ -194,6 +208,7 @@ struct CharServ_Config {
int mail_return_empty;
int allowed_job_flag;
int clear_parties;
};
extern struct CharServ_Config charserv_config;
@@ -220,7 +235,8 @@ struct auth_node {
unsigned changing_mapservers : 1;
uint8 version;
};
DBMap* char_get_authdb(); // uint32 account_id -> struct auth_node*
std::unordered_map<uint32, std::shared_ptr<struct auth_node>>& char_get_authdb();
struct online_char_data {
uint32 account_id;
@@ -229,8 +245,12 @@ struct online_char_data {
int waiting_disconnect;
short server; // -2: unknown server, -1: not connected, 0+: id of server
bool pincode_success;
public:
online_char_data( uint32 account_id );
};
DBMap* char_get_onlinedb(); // uint32 account_id -> struct online_char_data*
std::unordered_map<uint32, std::shared_ptr<struct online_char_data>>& char_get_onlinedb();
struct char_session_data {
bool auth; // whether the session is authed or not
@@ -258,9 +278,7 @@ struct char_session_data {
uint8 flag; // &1 - Retrieving guild bound items
};
struct mmo_charstatus;
DBMap* char_get_chardb(); // uint32 char_id -> struct mmo_charstatus*
std::unordered_map<uint32, std::shared_ptr<struct mmo_charstatus>>& char_get_chardb();
//Custom limits for the fame lists. [Skotlex]
extern int fame_list_size_chemist;
@@ -278,8 +296,7 @@ int char_search_mapserver(unsigned short map, uint32 ip, uint16 port);
int char_lan_subnetcheck(uint32 ip);
int char_count_users(void);
DBData char_create_online_data(DBKey key, va_list args);
int char_db_setoffline(DBKey key, DBData *data, va_list ap);
void char_db_setoffline( std::shared_ptr<struct online_char_data> character, int server );
void char_set_char_online(int map_id, uint32 char_id, uint32 account_id);
void char_set_char_offline(uint32 char_id, uint32 account_id);
void char_set_all_offline(int id);

View File

@@ -3,6 +3,9 @@
#include "char_clif.hpp"
#include <memory>
#include <unordered_map>
#include <stdlib.h>
#include <string.h>
@@ -15,6 +18,7 @@
#include "../common/sql.hpp"
#include "../common/strlib.hpp"
#include "../common/timer.hpp"
#include "../common/utilities.hpp"
#include "../common/utils.hpp"
#include "char.hpp"
@@ -23,6 +27,8 @@
#include "inter.hpp"
#include "packets.hpp"
using namespace rathena;
#if PACKETVER_SUPPORTS_PINCODE
bool pincode_allowed( char* pincode );
#endif
@@ -674,7 +680,7 @@ int chclif_parse_maplogin(int fd){
l_user[23] = '\0';
l_pass[23] = '\0';
ARR_FIND( 0, ARRAYLENGTH(map_server), i, map_server[i].fd <= 0 );
if( runflag != CHARSERVER_ST_RUNNING ||
if( !global_core->is_running() ||
i == ARRAYLENGTH(map_server) ||
strcmp(l_user, charserv_config.userid) != 0 ||
strcmp(l_pass, charserv_config.passwd) != 0 )
@@ -703,9 +709,6 @@ int chclif_parse_reqtoconnect(int fd, struct char_session_data* sd,uint32 ipl){
if( RFIFOREST(fd) < 17 ) // request to connect
return 0;
else {
struct auth_node* node;
DBMap *auth_db = char_get_authdb();
uint32 account_id = RFIFOL(fd,2);
uint32 login_id1 = RFIFOL(fd,6);
uint32 login_id2 = RFIFOL(fd,10);
@@ -735,20 +738,21 @@ int chclif_parse_reqtoconnect(int fd, struct char_session_data* sd,uint32 ipl){
WFIFOL(fd,0) = account_id;
WFIFOSET(fd,4);
if( runflag != CHARSERVER_ST_RUNNING ) {
if( !global_core->is_running() ){
chclif_reject(fd, 0); // rejected from server
return 1;
}
// search authentification
node = (struct auth_node*)idb_get(auth_db, account_id);
if( node != NULL &&
std::shared_ptr<struct auth_node> node = util::umap_find( char_get_authdb(), account_id);
if( node != nullptr &&
node->account_id == account_id &&
node->login_id1 == login_id1 &&
node->login_id2 == login_id2 /*&&
node->ip == ipl*/ )
{// authentication found (coming from map server)
idb_remove(auth_db, account_id);
char_get_authdb().erase(account_id);
char_auth_ok(fd, sd);
}
else
@@ -780,7 +784,7 @@ int chclif_parse_req_charlist(int fd, struct char_session_data* sd){
}
//Send player to map
void chclif_send_map_data( int fd, struct mmo_charstatus *cd, uint32 ipl, int map_server_index ){
void chclif_send_map_data( int fd, std::shared_ptr<struct mmo_charstatus> cd, uint32 ipl, int map_server_index ){
#if PACKETVER >= 20170315
int cmd = 0xAC5;
int size = 156;
@@ -806,13 +810,9 @@ int chclif_parse_charselect(int fd, struct char_session_data* sd,uint32 ipl){
FIFOSD_CHECK(3)
{
struct mmo_charstatus char_dat;
struct mmo_charstatus *cd;
char* data;
uint32 char_id;
struct auth_node* node;
int i, map_fd, server_id;
DBMap *auth_db = char_get_authdb();
DBMap *char_db_ = char_get_chardb();
int slot = RFIFOB(fd,2);
RFIFOSKIP(fd,3);
@@ -864,7 +864,7 @@ int chclif_parse_charselect(int fd, struct char_session_data* sd,uint32 ipl){
}
//Have to switch over to the DB instance otherwise data won't propagate [Kevin]
cd = (struct mmo_charstatus *)idb_get(char_db_, char_id);
std::shared_ptr<struct mmo_charstatus> cd = util::umap_find( char_get_chardb(), char_id );
if (charserv_config.log_char) {
char esc_name[NAME_LENGTH*2+1];
@@ -930,7 +930,8 @@ int chclif_parse_charselect(int fd, struct char_session_data* sd,uint32 ipl){
chclif_send_map_data( fd, cd, ipl, i );
// create temporary auth entry
CREATE(node, struct auth_node, 1);
std::shared_ptr<struct auth_node> node = std::make_shared<struct auth_node>();
node->account_id = sd->account_id;
node->char_id = cd->char_id;
node->login_id1 = sd->login_id1;
@@ -939,8 +940,8 @@ int chclif_parse_charselect(int fd, struct char_session_data* sd,uint32 ipl){
node->expiration_time = sd->expiration_time;
node->group_id = sd->group_id;
node->ip = ipl;
idb_put(auth_db, sd->account_id, node);
char_get_authdb()[node->account_id] = node;
}
return 1;
}
@@ -1363,12 +1364,16 @@ int chclif_parse(int fd) {
if(session[fd]->flag.eof) {
if( sd != NULL && sd->auth ) { // already authed client
DBMap *online_char_db = char_get_onlinedb();
struct online_char_data* data = (struct online_char_data*)idb_get(online_char_db, sd->account_id);
if( data != NULL && data->fd == fd)
std::shared_ptr<struct online_char_data> data = util::umap_find( char_get_onlinedb(), sd->account_id );
if( data != nullptr && data->fd == fd ){
data->fd = -1;
if( data == NULL || data->server == -1) //If it is not in any server, send it offline. [Skotlex]
}
// If it is not in any server, send it offline. [Skotlex]
if( data == nullptr || data->server == -1 ){
char_set_char_offline(-1,sd->account_id);
}
}
do_close(fd);
return 0;

View File

@@ -74,7 +74,7 @@ int cnslif_parse(const char* buf)
if( n == 2 && strcmpi("server", type) == 0 ){
if( strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || strcmpi("quit", command) == 0 ){
runflag = 0;
global_core->signal_shutdown();
}
else if( strcmpi("alive", command) == 0 || strcmpi("status", command) == 0 )
ShowInfo(CL_CYAN "Console: " CL_BOLD "I'm Alive." CL_RESET "\n");

View File

@@ -3,6 +3,8 @@
#include "char_logif.hpp"
#include <memory>
#include <stdlib.h>
#include <string.h>
@@ -11,6 +13,7 @@
#include "../common/sql.hpp"
#include "../common/strlib.hpp"
#include "../common/timer.hpp"
#include "../common/utilities.hpp"
#include "../common/utils.hpp"
#include "char.hpp"
@@ -19,6 +22,8 @@
#include "inter.hpp"
#include "int_guild.hpp"
using namespace rathena;
//early declaration
void chlogif_on_ready(void);
void chlogif_on_disconnect(void);
@@ -59,10 +64,9 @@ void chlogif_pincode_start(int fd, struct char_session_data* sd){
}else{
if( !(charserv_config.pincode_config.pincode_changetime)
|| ( sd->pincode_change + charserv_config.pincode_config.pincode_changetime ) > time(NULL) ){
DBMap* online_char_db = char_get_onlinedb();
struct online_char_data* node = (struct online_char_data*)idb_get( online_char_db, sd->account_id );
std::shared_ptr<struct online_char_data> node = util::umap_find( char_get_onlinedb(), sd->account_id );
if( node != NULL && node->pincode_success ){
if( node != nullptr && node->pincode_success ){
// User has already passed the check
chclif_pincode_sendstate( fd, sd, PINCODE_PASSED );
}else{
@@ -82,21 +86,6 @@ void chlogif_pincode_start(int fd, struct char_session_data* sd){
}
#endif
/**
* Load this character's account id into the 'online accounts' packet
* @see DBApply
*/
int chlogif_send_acc_tologin_sub(DBKey key, DBData *data, va_list ap) {
struct online_char_data* character = (struct online_char_data*)db_data2ptr(data);
int* i = va_arg(ap, int*);
if(character->server > -1) {
WFIFOL(login_fd,8+(*i)*4) = character->account_id;
(*i)++;
return 1;
}
return 0;
}
/**
* Timered function to send all account_id connected to login-serv
* @param tid : Timer id
@@ -107,14 +96,20 @@ int chlogif_send_acc_tologin_sub(DBKey key, DBData *data, va_list ap) {
*/
TIMER_FUNC(chlogif_send_acc_tologin){
if ( chlogif_isconnected() ){
DBMap* online_char_db = char_get_onlinedb();
// send account list to login server
int users = online_char_db->size(online_char_db);
int users = char_get_onlinedb().size();
int i = 0;
WFIFOHEAD(login_fd,8+users*4);
WFIFOW(login_fd,0) = 0x272d;
online_char_db->foreach(online_char_db, chlogif_send_acc_tologin_sub, &i, users);
for( const auto& pair : char_get_onlinedb() ){
std::shared_ptr<struct online_char_data> character = pair.second;
if( character->server > -1 ){
WFIFOL( login_fd, 8 + i * 4 ) = character->account_id;
i++;
}
}
WFIFOW(login_fd,2) = 8+ i*4;
WFIFOL(login_fd,4) = i;
WFIFOSET(login_fd,WFIFOW(login_fd,2));
@@ -434,18 +429,17 @@ int chlogif_parse_ackchangesex(int fd)
return 0;
else {
unsigned char buf[7];
int acc = RFIFOL(fd,2);
uint32 acc = RFIFOL(fd,2);
int sex = RFIFOB(fd,6);
RFIFOSKIP(fd,7);
if (acc > 0) { // TODO: Is this even possible?
unsigned char i;
int char_id = 0, class_ = 0, guild_id = 0;
DBMap* auth_db = char_get_authdb();
struct auth_node* node = (struct auth_node*)idb_get(auth_db, acc);
std::shared_ptr<struct auth_node> node = util::umap_find( char_get_authdb(), acc );
SqlStmt *stmt;
if (node != NULL)
if (node != nullptr)
node->sex = sex;
// get characters
@@ -550,13 +544,13 @@ int chlogif_parse_askkick(int fd){
if (RFIFOREST(fd) < 6)
return 0;
else {
DBMap* online_char_db = char_get_onlinedb();
DBMap* auth_db = char_get_authdb();
int aid = RFIFOL(fd,2);
struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, aid);
uint32 aid = RFIFOL(fd,2);
RFIFOSKIP(fd,6);
if( character != NULL )
{// account is already marked as online!
std::shared_ptr<struct online_char_data> character = util::umap_find( char_get_onlinedb(), aid );
// account is already marked as online!
if( character != nullptr ){
if( character->server > -1 )
{ //Kick it from the map server it is on.
mapif_disconnectplayer(map_server[character->server].fd, character->account_id, character->char_id, 2);
@@ -577,7 +571,9 @@ int chlogif_parse_askkick(int fd){
char_set_char_offline(-1, aid);
}
}
idb_remove(auth_db, aid);// reject auth attempts from map-server
// reject auth attempts from map-server
char_get_authdb().erase( aid );
}
return 1;
}
@@ -813,16 +809,6 @@ void chlogif_reset(void){
exit(EXIT_FAILURE);
}
/// Checks the conditions for the server to stop.
/// Releases the cookie when all characters are saved.
/// If all the conditions are met, it stops the core loop.
void chlogif_check_shutdown(void)
{
if( runflag != CHARSERVER_ST_SHUTDOWN )
return;
runflag = CORE_ST_STOP;
}
/// Called when the connection to Login Server is disconnected.
void chlogif_on_disconnect(void){
ShowWarning("Connection to Login Server lost.\n\n");
@@ -833,8 +819,6 @@ void chlogif_on_ready(void)
{
int i;
chlogif_check_shutdown();
//Send online accounts to login server.
chlogif_send_acc_tologin(INVALID_TIMER, gettick(), 0, 0);

View File

@@ -3,6 +3,8 @@
#include "char_mapif.hpp"
#include <memory>
#include <stdlib.h>
#include <string.h> //memcpy
@@ -12,11 +14,14 @@
#include "../common/sql.hpp"
#include "../common/strlib.hpp"
#include "../common/timer.hpp"
#include "../common/utilities.hpp"
#include "char.hpp"
#include "char_logif.hpp"
#include "inter.hpp"
using namespace rathena;
/**
* Packet send to all map-servers, attach to ourself
* @param buf: packet to send in form of an array buffer
@@ -279,7 +284,7 @@ int chmapif_parse_askscdata(int fd){
int aid, cid;
aid = RFIFOL(fd,2);
cid = RFIFOL(fd,6);
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT type, tick, val1, val2, val3, val4 from `%s` WHERE `account_id` = '%d' AND `char_id`='%d'",
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT type, tick, val1, val2, val3, val4, tick_total, tick_time from `%s` WHERE `account_id` = '%d' AND `char_id`='%d'",
schema_config.scdata_db, aid, cid) )
{
Sql_ShowDebug(sql_handle);
@@ -303,6 +308,8 @@ int chmapif_parse_askscdata(int fd){
Sql_GetData(sql_handle, 3, &data, NULL); scdata.val2 = atoi(data);
Sql_GetData(sql_handle, 4, &data, NULL); scdata.val3 = atoi(data);
Sql_GetData(sql_handle, 5, &data, NULL); scdata.val4 = atoi(data);
Sql_GetData(sql_handle, 6, &data, NULL); scdata.tick_total = strtoll(data, nullptr, 10);
Sql_GetData(sql_handle, 7, &data, NULL); scdata.tick_time = strtoll(data, nullptr, 10);
memcpy(WFIFOP(fd, 14+count*sizeof(struct status_change_data)), &scdata, sizeof(struct status_change_data));
}
if (count >= 50)
@@ -357,21 +364,29 @@ int chmapif_parse_regmapuser(int fd, int id){
return 0;
else {
//TODO: When data mismatches memory, update guild/party online/offline states.
DBMap* online_char_db = char_get_onlinedb();
int i;
map_server[id].users = RFIFOW(fd,4);
online_char_db->foreach(online_char_db,char_db_setoffline,id); //Set all chars from this server as 'unknown'
for(i = 0; i < map_server[id].users; i++) {
int aid = RFIFOL(fd,6+i*8);
int cid = RFIFOL(fd,6+i*8+4);
struct online_char_data* character = (struct online_char_data*)idb_ensure(online_char_db, aid, char_create_online_data);
if( character->server > -1 && character->server != id )
{
ShowNotice("Set map user: Character (%d:%d) marked on map server %d, but map server %d claims to have (%d:%d) online!\n",
character->account_id, character->char_id, character->server, id, aid, cid);
mapif_disconnectplayer(map_server[character->server].fd, character->account_id, character->char_id, 2);
// Set all chars from this server as 'unknown'
for( const auto& pair : char_get_onlinedb() ){
char_db_setoffline( pair.second, id );
}
for( int i = 0; i < map_server[id].users; i++ ){
uint32 aid = RFIFOL(fd,6+i*8);
uint32 cid = RFIFOL(fd,6+i*8+4);
std::shared_ptr<struct online_char_data> character = util::umap_find( char_get_onlinedb(), aid );
if( character != nullptr ){
if( character->server > -1 && character->server != id ){
ShowNotice("Set map user: Character (%d:%d) marked on map server %d, but map server %d claims to have (%d:%d) online!\n",
character->account_id, character->char_id, character->server, id, aid, cid);
mapif_disconnectplayer(map_server[character->server].fd, character->account_id, character->char_id, 2);
}
}else{
character = std::make_shared<struct online_char_data>( aid );
}
character->server = id;
character->char_id = cid;
}
@@ -392,9 +407,8 @@ int chmapif_parse_reqsavechar(int fd, int id){
if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
return 0;
else {
int aid = RFIFOL(fd,4), cid = RFIFOL(fd,8), size = RFIFOW(fd,2);
struct online_char_data* character;
DBMap* online_char_db = char_get_onlinedb();
uint32 aid = RFIFOL( fd, 4 ), cid = RFIFOL( fd, 8 );
uint16 size = RFIFOW( fd, 2 );
if (size - 13 != sizeof(struct mmo_charstatus))
{
@@ -402,11 +416,11 @@ int chmapif_parse_reqsavechar(int fd, int id){
RFIFOSKIP(fd,size);
return 1;
}
std::shared_ptr<struct online_char_data> character = util::umap_find( char_get_onlinedb(), aid );
//Check account only if this ain't final save. Final-save goes through because of the char-map reconnect
if (RFIFOB(fd,12) || RFIFOB(fd,13) || (
(character = (struct online_char_data*)idb_get(online_char_db, aid)) != NULL &&
character->char_id == cid))
{
if( RFIFOB( fd, 12 ) || RFIFOB( fd, 13 ) || ( character != nullptr && character->char_id == cid ) ){
struct mmo_charstatus char_dat;
memcpy(&char_dat, RFIFOP(fd,13), sizeof(struct mmo_charstatus));
char_mmo_char_tosql(cid, &char_dat);
@@ -458,15 +472,12 @@ int chmapif_parse_authok(int fd){
uint32 ip = RFIFOL(fd,14);
RFIFOSKIP(fd,18);
if( runflag != CHARSERVER_ST_RUNNING ){
if( !global_core->is_running() ){
chmapif_charselres(fd,account_id,0);
}else{
struct auth_node* node;
DBMap* auth_db = char_get_authdb();
DBMap* online_char_db = char_get_onlinedb();
// create temporary auth entry
CREATE(node, struct auth_node, 1);
std::shared_ptr<struct auth_node> node = std::make_shared<struct auth_node>();
node->account_id = account_id;
node->char_id = 0;
node->login_id1 = login_id1;
@@ -475,16 +486,18 @@ int chmapif_parse_authok(int fd){
node->ip = ntohl(ip);
//node->expiration_time = 0; // unlimited/unknown time by default (not display in map-server)
//node->gmlevel = 0;
idb_put(auth_db, account_id, node);
char_get_authdb()[node->account_id] = node;
//Set char to "@ char select" in online db [Kevin]
char_set_charselect(account_id);
{
struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, account_id);
if( character != NULL ){
character->pincode_success = true;
}
std::shared_ptr<struct online_char_data> character = util::umap_find( char_get_onlinedb(), account_id );
if( character != nullptr ){
character->pincode_success = true;
}
chmapif_charselres(fd,account_id,1);
}
}
@@ -596,30 +609,28 @@ int chmapif_parse_reqchangemapserv(int fd){
return 0;
else {
int map_id, map_fd = -1;
struct mmo_charstatus* char_data;
struct mmo_charstatus char_dat;
DBMap* char_db_ = char_get_chardb();
map_id = char_search_mapserver(RFIFOW(fd,18), ntohl(RFIFOL(fd,24)), ntohs(RFIFOW(fd,28))); //Locate mapserver by ip and port.
if (map_id >= 0)
map_fd = map_server[map_id].fd;
//Char should just had been saved before this packet, so this should be safe. [Skotlex]
char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14));
if (char_data == NULL) { //Really shouldn't happen.
char_mmo_char_fromsql(RFIFOL(fd,14), &char_dat, true);
char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14));
uint32 char_id = RFIFOL( fd, 14 );
// Char should just had been saved before this packet, so this should be safe. [Skotlex]
std::shared_ptr<struct mmo_charstatus> char_data = util::umap_find( char_get_chardb(), char_id );
// Really shouldn't happen.
if( char_data == nullptr ){
char_mmo_char_fromsql( char_id, &char_dat, true );
char_data = util::umap_find( char_get_chardb(), char_id );
}
if( runflag == CHARSERVER_ST_RUNNING &&
if( global_core->is_running() &&
session_isActive(map_fd) &&
char_data )
{ //Send the map server the auth of this player.
struct online_char_data* data;
struct auth_node* node;
DBMap* auth_db = char_get_authdb();
DBMap* online_char_db = char_get_onlinedb();
int aid = RFIFOL(fd,2);
uint32 aid = RFIFOL( fd, 2 );
//Update the "last map" as this is where the player must be spawned on the new map server.
char_data->last_point.map = RFIFOW(fd,18);
@@ -628,9 +639,10 @@ int chmapif_parse_reqchangemapserv(int fd){
char_data->sex = RFIFOB(fd,30);
// create temporary auth entry
CREATE(node, struct auth_node, 1);
std::shared_ptr<struct auth_node> node = std::make_shared<struct auth_node>();
node->account_id = aid;
node->char_id = RFIFOL(fd,14);
node->char_id = char_id;
node->login_id1 = RFIFOL(fd,6);
node->login_id2 = RFIFOL(fd,10);
node->sex = RFIFOB(fd,30);
@@ -638,9 +650,15 @@ int chmapif_parse_reqchangemapserv(int fd){
node->ip = ntohl(RFIFOL(fd,31));
node->group_id = RFIFOL(fd,35);
node->changing_mapservers = 1;
idb_put(auth_db, aid, node);
data = (struct online_char_data*)idb_ensure(online_char_db, aid, char_create_online_data);
char_get_authdb()[node->account_id] = node;
std::shared_ptr<struct online_char_data> data = util::umap_find( char_get_onlinedb(), aid );
if( data == nullptr ){
data = std::make_shared<struct online_char_data>( aid );
}
data->char_id = char_data->char_id;
data->server = map_id; //Update server where char is.
@@ -942,14 +960,14 @@ int chmapif_parse_save_scdata(int fd){
int i;
StringBuf_Init(&buf);
StringBuf_Printf(&buf, "INSERT INTO `%s` (`account_id`, `char_id`, `type`, `tick`, `val1`, `val2`, `val3`, `val4`) VALUES ", schema_config.scdata_db);
StringBuf_Printf(&buf, "INSERT INTO `%s` (`account_id`, `char_id`, `type`, `tick`, `tick_total`, `tick_time`, `val1`, `val2`, `val3`, `val4`) VALUES ", schema_config.scdata_db);
for( i = 0; i < count; ++i )
{
memcpy (&data, RFIFOP(fd, 14+i*sizeof(struct status_change_data)), sizeof(struct status_change_data));
if( i > 0 )
StringBuf_AppendStr(&buf, ", ");
StringBuf_Printf(&buf, "('%d','%d','%hu','%" PRtf "','%ld','%ld','%ld','%ld')", aid, cid,
data.type, data.tick, data.val1, data.val2, data.val3, data.val4);
StringBuf_Printf(&buf, "('%d','%d','%hu','%" PRtf "','%" PRtf "','%" PRtf "','%ld','%ld','%ld','%ld')", aid, cid,
data.type, data.tick, data.tick_total, data.tick_time, data.val1, data.val2, data.val3, data.val4);
}
if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) )
Sql_ShowDebug(sql_handle);
@@ -988,14 +1006,9 @@ int chmapif_parse_reqauth(int fd, int id){
uint32 login_id1;
unsigned char sex;
uint32 ip;
struct auth_node* node;
struct mmo_charstatus* cd;
struct mmo_charstatus char_dat;
bool autotrade;
DBMap* auth_db = char_get_authdb();
DBMap* char_db_ = char_get_chardb();
account_id = RFIFOL(fd,2);
char_id = RFIFOL(fd,6);
login_id1 = RFIFOL(fd,10);
@@ -1004,14 +1017,16 @@ int chmapif_parse_reqauth(int fd, int id){
autotrade = RFIFOB(fd,19) != 0;
RFIFOSKIP(fd,20);
node = (struct auth_node*)idb_get(auth_db, account_id);
cd = (struct mmo_charstatus*)uidb_get(char_db_,char_id);
if( cd == NULL )
{ //Really shouldn't happen. (or autotrade)
char_mmo_char_fromsql(char_id, &char_dat, true);
cd = (struct mmo_charstatus*)uidb_get(char_db_,char_id);
std::shared_ptr<struct auth_node> node = util::umap_find( char_get_authdb(), account_id );
std::shared_ptr<struct mmo_charstatus> cd = util::umap_find( char_get_chardb(), char_id );
if( cd == nullptr ){
// Really shouldn't happen. (or autotrade)
char_mmo_char_fromsql( char_id, &char_dat, true );
cd = util::umap_find( char_get_chardb(), char_id );
}
if( runflag == CHARSERVER_ST_RUNNING && autotrade && cd ){
if( global_core->is_running() && autotrade && cd ){
uint16 mmo_charstatus_len = sizeof(struct mmo_charstatus) + 25;
WFIFOHEAD(fd,mmo_charstatus_len);
@@ -1023,11 +1038,11 @@ int chmapif_parse_reqauth(int fd, int id){
WFIFOL(fd,16) = 0;
WFIFOL(fd,20) = 0;
WFIFOB(fd,24) = 0;
memcpy(WFIFOP(fd,25), cd, sizeof(struct mmo_charstatus));
memcpy( WFIFOP( fd, 25 ), cd.get(), sizeof(struct mmo_charstatus));
WFIFOSET(fd, WFIFOW(fd,2));
char_set_char_online(id, char_id, account_id);
} else if( runflag == CHARSERVER_ST_RUNNING &&
} else if( global_core->is_running() &&
cd != NULL &&
node != NULL &&
node->account_id == account_id &&
@@ -1050,11 +1065,11 @@ int chmapif_parse_reqauth(int fd, int id){
WFIFOL(fd,16) = (uint32)node->expiration_time; // FIXME: will wrap to negative after "19-Jan-2038, 03:14:07 AM GMT"
WFIFOL(fd,20) = node->group_id;
WFIFOB(fd,24) = node->changing_mapservers;
memcpy(WFIFOP(fd,25), cd, sizeof(struct mmo_charstatus));
memcpy( WFIFOP( fd, 25 ), cd.get(), sizeof( struct mmo_charstatus ) );
WFIFOSET(fd, WFIFOW(fd,2));
// only use the auth once and mark user online
idb_remove(auth_db, account_id);
char_get_authdb().erase( account_id );
char_set_char_online(id, char_id, account_id);
} else {// auth failed
WFIFOHEAD(fd,19);
@@ -1492,7 +1507,6 @@ void chmapif_server_reset(int id){
int j = 0;
unsigned char buf[16384];
int fd = map_server[id].fd;
DBMap* online_char_db = char_get_onlinedb();
//Notify other map servers that this one is gone. [Skotlex]
WBUFW(buf,0) = 0x2b20;
@@ -1505,7 +1519,12 @@ void chmapif_server_reset(int id){
WBUFW(buf,2) = j * 4 + 10;
chmapif_sendallwos(fd, buf, WBUFW(buf,2));
}
online_char_db->foreach(online_char_db,char_db_setoffline,id); //Tag relevant chars as 'in disconnected' server.
// Tag relevant chars as 'in disconnected' server.
for( const auto& pair : char_get_onlinedb() ){
char_db_setoffline( pair.second, id );
}
chmapif_server_destroy(id);
chmapif_server_init(id);
}

View File

@@ -3,6 +3,9 @@
#include "int_auction.hpp"
#include <memory>
#include <unordered_map>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -14,35 +17,37 @@
#include "../common/sql.hpp"
#include "../common/strlib.hpp"
#include "../common/timer.hpp"
#include "../common/utilities.hpp"
#include "char.hpp"
#include "char_mapif.hpp"
#include "inter.hpp"
#include "int_mail.hpp"
static DBMap* auction_db_ = NULL; // int auction_id -> struct auction_data*
using namespace rathena;
void auction_delete(struct auction_data *auction);
// int auction_id -> struct auction_data*
static std::unordered_map<uint32, std::shared_ptr<struct auction_data>> auction_db;
void auction_delete( std::shared_ptr<struct auction_data> auction );
TIMER_FUNC(auction_end_timer);
int auction_count(uint32 char_id, bool buy)
{
int i = 0;
struct auction_data *auction;
DBIterator *iter = db_iterator(auction_db_);
for( auction = (struct auction_data *)dbi_first(iter); dbi_exists(iter); auction = (struct auction_data *)dbi_next(iter) )
{
if( (buy && auction->buyer_id == char_id) || (!buy && auction->seller_id == char_id) )
for( const auto& pair : auction_db ){
std::shared_ptr<struct auction_data> auction = pair.second;
if( ( buy && auction->buyer_id == char_id ) || ( !buy && auction->seller_id == char_id ) ){
i++;
}
}
dbi_destroy(iter);
return i;
}
void auction_save(struct auction_data *auction)
{
void auction_save( std::shared_ptr<struct auction_data> auction ){
int j;
StringBuf buf;
SqlStmt* stmt;
@@ -76,8 +81,7 @@ void auction_save(struct auction_data *auction)
StringBuf_Destroy(&buf);
}
unsigned int auction_create(struct auction_data *auction)
{
uint32 auction_create( std::shared_ptr<struct auction_data> auction ){
int j;
StringBuf buf;
SqlStmt* stmt;
@@ -119,7 +123,6 @@ unsigned int auction_create(struct auction_data *auction)
}
else
{
struct auction_data *auction_;
t_tick tick = auction->hours * 3600000;
auction->item.amount = 1;
@@ -130,9 +133,7 @@ unsigned int auction_create(struct auction_data *auction)
auction->auction_end_timer = add_timer( gettick() + tick , auction_end_timer, auction->auction_id, 0);
ShowInfo("New Auction %u | time left %" PRtf " ms | By %s.\n", auction->auction_id, tick, auction->seller_name);
CREATE(auction_, struct auction_data, 1);
memcpy(auction_, auction, sizeof(struct auction_data));
idb_put(auction_db_, auction_->auction_id, auction_);
auction_db[auction->auction_id] = auction;
}
SqlStmt_Free(stmt);
@@ -152,9 +153,9 @@ void mapif_Auction_message(uint32 char_id, unsigned char result)
}
TIMER_FUNC(auction_end_timer){
struct auction_data *auction;
if( (auction = (struct auction_data *)idb_get(auction_db_, id)) != NULL )
{
std::shared_ptr<struct auction_data> auction = util::umap_find( auction_db, static_cast<uint32>( id ) );
if( auction != nullptr ){
if( auction->buyer_id )
{
mail_sendmail(0, msg_txt(200), auction->buyer_id, auction->buyer_name, msg_txt(201), msg_txt(202), 0, &auction->item, 1);
@@ -173,8 +174,7 @@ TIMER_FUNC(auction_end_timer){
return 0;
}
void auction_delete(struct auction_data *auction)
{
void auction_delete( std::shared_ptr<struct auction_data> auction ){
unsigned int auction_id = auction->auction_id;
if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `auction_id` = '%d'", schema_config.auction_db, auction_id) )
@@ -183,7 +183,7 @@ void auction_delete(struct auction_data *auction)
if( auction->auction_end_timer != INVALID_TIMER )
delete_timer(auction->auction_end_timer, auction_end_timer);
idb_remove(auction_db_, auction_id);
auction_db.erase( auction_id );
}
void inter_auctions_fromsql(void)
@@ -214,8 +214,8 @@ void inter_auctions_fromsql(void)
while( SQL_SUCCESS == Sql_NextRow(sql_handle) )
{
struct item *item;
struct auction_data *auction;
CREATE(auction, struct auction_data, 1);
std::shared_ptr<struct auction_data> auction = std::make_shared<struct auction_data>();
Sql_GetData(sql_handle, 0, &data, NULL); auction->auction_id = atoi(data);
Sql_GetData(sql_handle, 1, &data, NULL); auction->seller_id = atoi(data);
Sql_GetData(sql_handle, 2, &data, NULL); safestrncpy(auction->seller_name, data, NAME_LENGTH);
@@ -261,7 +261,8 @@ void inter_auctions_fromsql(void)
endtick = tick + 10000; // 10 Second's to process ended auctions
auction->auction_end_timer = add_timer(endtick, auction_end_timer, auction->auction_id, 0);
idb_put(auction_db_, auction->auction_id, auction);
auction_db[auction->auction_id] = auction;
}
Sql_FreeResult(sql_handle);
@@ -288,14 +289,13 @@ void mapif_parse_Auction_requestlist(int fd)
int price = RFIFOL(fd,10);
short type = RFIFOW(fd,8), page = max(1,RFIFOW(fd,14));
unsigned char buf[5 * sizeof(struct auction_data)];
DBIterator *iter = db_iterator(auction_db_);
struct auction_data *auction;
short i = 0, j = 0, pages = 1;
memcpy(searchtext, RFIFOP(fd,16), NAME_LENGTH);
for( auction = static_cast<auction_data *>(dbi_first(iter)); dbi_exists(iter); auction = static_cast<auction_data *>(dbi_next(iter)) )
{
for( const auto& pair : auction_db ){
std::shared_ptr<struct auction_data> auction = pair.second;
if( (type == 0 && auction->type != IT_ARMOR && auction->type != IT_PETARMOR) ||
(type == 1 && auction->type != IT_WEAPON) ||
(type == 2 && auction->type != IT_CARD) ||
@@ -316,10 +316,9 @@ void mapif_parse_Auction_requestlist(int fd)
if( page != pages )
continue; // This is not the requested Page
memcpy(WBUFP(buf, j * len), auction, len);
memcpy( WBUFP( buf, j * len ), auction.get(), len );
j++; // Found Results
}
dbi_destroy(iter);
mapif_Auction_sendlist(fd, char_id, j, pages, buf);
}
@@ -337,15 +336,22 @@ void mapif_Auction_register(int fd, struct auction_data *auction)
void mapif_parse_Auction_register(int fd)
{
struct auction_data auction;
if( RFIFOW(fd,2) != sizeof(struct auction_data) + 4 )
return;
memcpy(&auction, RFIFOP(fd,4), sizeof(struct auction_data));
if( auction_count(auction.seller_id, false) < 5 )
auction.auction_id = auction_create(&auction);
struct auction_data* auction = reinterpret_cast<struct auction_data*>( RFIFOP( fd, 4 ) );
mapif_Auction_register(fd, &auction);
if( auction_count( auction->seller_id, false ) < 5 ){
std::shared_ptr<struct auction_data> auction2 = std::make_shared<struct auction_data>();
memcpy( auction2.get(), auction, sizeof( struct auction_data ) );
auction2->auction_id = auction_create( auction2 );
auction = auction2.get();
}
mapif_Auction_register( fd, auction );
}
void mapif_Auction_cancel(int fd, uint32 char_id, unsigned char result)
@@ -360,10 +366,10 @@ void mapif_Auction_cancel(int fd, uint32 char_id, unsigned char result)
void mapif_parse_Auction_cancel(int fd)
{
uint32 char_id = RFIFOL(fd,2), auction_id = RFIFOL(fd,6);
struct auction_data *auction;
if( (auction = (struct auction_data *)idb_get(auction_db_, auction_id)) == NULL )
{
std::shared_ptr<struct auction_data> auction = util::umap_find( auction_db, auction_id );
if( auction == nullptr ){
mapif_Auction_cancel(fd, char_id, 1); // Bid Number is Incorrect
return;
}
@@ -398,10 +404,9 @@ void mapif_Auction_close(int fd, uint32 char_id, unsigned char result)
void mapif_parse_Auction_close(int fd)
{
uint32 char_id = RFIFOL(fd,2), auction_id = RFIFOL(fd,6);
struct auction_data *auction;
std::shared_ptr<struct auction_data> auction = util::umap_find( auction_db, auction_id );
if( (auction = (struct auction_data *)idb_get(auction_db_, auction_id)) == NULL )
{
if( auction == nullptr ){
mapif_Auction_close(fd, char_id, 2); // Bid Number is Incorrect
return;
}
@@ -442,10 +447,9 @@ void mapif_parse_Auction_bid(int fd)
{
uint32 char_id = RFIFOL(fd,4), auction_id = RFIFOL(fd,8);
int bid = RFIFOL(fd,12);
struct auction_data *auction;
std::shared_ptr<struct auction_data> auction = util::umap_find( auction_db, auction_id );
if( (auction = (struct auction_data *)idb_get(auction_db_, auction_id)) == NULL || auction->price >= bid || auction->seller_id == char_id )
{
if( auction == nullptr || auction->price >= bid || auction->seller_id == char_id ){
mapif_Auction_bid(fd, char_id, bid, 0); // You have failed to bid in the auction
return;
}
@@ -508,7 +512,6 @@ int inter_auction_parse_frommap(int fd)
int inter_auction_sql_init(void)
{
auction_db_ = idb_alloc(DB_OPT_RELEASE_DATA);
inter_auctions_fromsql();
return 0;
@@ -516,7 +519,7 @@ int inter_auction_sql_init(void)
void inter_auction_sql_final(void)
{
auction_db_->destroy(auction_db_,NULL);
auction_db.clear();
return;
}

View File

@@ -3,6 +3,10 @@
#include "int_clan.hpp"
#include <memory>
#include <unordered_map>
#include <vector>
#include <stdlib.h>
#include <string.h> //memset
@@ -17,8 +21,10 @@
#include "char_mapif.hpp"
#include "inter.hpp"
//clan cache
static DBMap* clan_db; // int clan_id -> struct clan*
// int clan_id -> struct clan*
static std::unordered_map<int32, std::shared_ptr<struct clan>> clan_db;
using namespace rathena;
int inter_clan_removemember_tosql(uint32 account_id, uint32 char_id){
if( SQL_ERROR == Sql_Query( sql_handle, "UPDATE `%s` SET `clan_id` = '0' WHERE `char_id` = '%d'", schema_config.char_db, char_id ) ){
@@ -29,16 +35,15 @@ int inter_clan_removemember_tosql(uint32 account_id, uint32 char_id){
}
}
struct clan* inter_clan_fromsql(int clan_id){
struct clan* clan;
std::shared_ptr<struct clan> inter_clan_fromsql(int clan_id){
char* data;
size_t len;
int i;
if( clan_id <= 0 )
return NULL;
return nullptr;
clan = (struct clan*)idb_get(clan_db, clan_id);
std::shared_ptr<struct clan> clan = util::umap_find( clan_db, clan_id );
if( clan ){
return clan;
@@ -46,15 +51,14 @@ struct clan* inter_clan_fromsql(int clan_id){
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `name`, `master`, `mapname`, `max_member` FROM `%s` WHERE `clan_id`='%d'", schema_config.clan_table, clan_id) ){
Sql_ShowDebug(sql_handle);
return NULL;
return nullptr;
}
if( SQL_SUCCESS != Sql_NextRow(sql_handle) ){
return NULL;// Clan does not exists.
return nullptr; // Clan does not exists.
}
CREATE(clan, struct clan, 1);
memset(clan, 0, sizeof(struct clan));
clan = std::make_shared<struct clan>();
clan->id = clan_id;
Sql_GetData(sql_handle, 0, &data, &len); memcpy(clan->name, data, min(len, NAME_LENGTH));
@@ -73,8 +77,7 @@ struct clan* inter_clan_fromsql(int clan_id){
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `opposition`,`alliance_id`,`name` FROM `%s` WHERE `clan_id`='%d'", schema_config.clan_alliance_table, clan_id) ){
Sql_ShowDebug(sql_handle);
aFree(clan);
return NULL;
return nullptr;
}
for( i = 0; i < MAX_CLANALLIANCE && SQL_SUCCESS == Sql_NextRow(sql_handle); i++ ){
@@ -85,7 +88,7 @@ struct clan* inter_clan_fromsql(int clan_id){
Sql_GetData(sql_handle, 2, &data, &len); memcpy(a->name, data, zmin(len, NAME_LENGTH));
}
idb_put( clan_db, clan_id, clan);
clan_db[clan->id] = clan;
if (charserv_config.save_log)
ShowInfo("Clan loaded (%d - %s)\n", clan_id, clan->name);
@@ -94,24 +97,22 @@ struct clan* inter_clan_fromsql(int clan_id){
}
int mapif_clan_info( int fd ){
DBIterator *iter;
int offset;
struct clan* clan;
int length;
length = 4 + db_size(clan_db) * sizeof( struct clan );
length = 4 + clan_db.size() * sizeof( struct clan );
WFIFOHEAD( fd, length );
WFIFOW( fd, 0 ) = 0x38A0;
WFIFOW( fd, 2 ) = length;
offset = 4;
iter = db_iterator(clan_db);
for( clan = (struct clan*)dbi_first(iter); dbi_exists(iter); clan = (struct clan*)dbi_next(iter) ){
memcpy( WFIFOP( fd, offset ), clan, sizeof( struct clan ) );
for( const auto& pair : clan_db ){
std::shared_ptr<struct clan> clan = pair.second;
memcpy( WFIFOP( fd, offset ), clan.get(), sizeof( struct clan ) );
offset += sizeof( struct clan );
}
dbi_destroy(iter);
WFIFOSET( fd, length );
@@ -138,7 +139,7 @@ static int mapif_parse_clan_message( int fd ){
return 0;
}
static void mapif_clan_refresh_onlinecount( int fd, struct clan* clan ){
static void mapif_clan_refresh_onlinecount( int fd, std::shared_ptr<struct clan> clan ){
unsigned char buf[8];
WBUFW(buf,0) = 0x38A2;
@@ -149,9 +150,10 @@ static void mapif_clan_refresh_onlinecount( int fd, struct clan* clan ){
}
static void mapif_parse_clan_member_left( int fd ){
struct clan* clan = (struct clan*)idb_get(clan_db, RFIFOL(fd,2) );
std::shared_ptr<struct clan> clan = util::umap_find( clan_db, static_cast<int32>( RFIFOL( fd, 2 ) ) );
if( clan == NULL ){ // Unknown clan
// Unknown clan
if( clan == nullptr ){
return;
}
@@ -163,9 +165,10 @@ static void mapif_parse_clan_member_left( int fd ){
}
static void mapif_parse_clan_member_joined( int fd ){
struct clan* clan = (struct clan*)idb_get(clan_db, RFIFOL(fd,2) );
std::shared_ptr<struct clan> clan = util::umap_find( clan_db, static_cast<int32>( RFIFOL( fd, 2 ) ) );
if( clan == NULL ){ // Unknown clan
// Unknown clan
if( clan == nullptr ){
return;
}
@@ -203,45 +206,28 @@ int inter_clan_parse_frommap( int fd ){
// Initialize clan sql
int inter_clan_init(void){
char* data;
int* clan_ids;
int amount;
clan_db = idb_alloc(DB_OPT_RELEASE_DATA);
if( SQL_ERROR == Sql_Query( sql_handle, "SELECT `clan_id` FROM `%s`", schema_config.clan_table ) ){
Sql_ShowDebug(sql_handle);
return 1;
}
amount = (int)Sql_NumRows( sql_handle );
std::vector<int32> clan_ids;
if( amount > 0 ){
int i;
while( SQL_SUCCESS == Sql_NextRow( sql_handle ) ){
char* data;
Sql_GetData( sql_handle, 0, &data, nullptr );
clan_ids.push_back( atoi( data ) );
}
CREATE( clan_ids, int, amount );
i = 0;
Sql_FreeResult( sql_handle );
while( SQL_SUCCESS == Sql_NextRow(sql_handle) ){
Sql_GetData(sql_handle, 0, &data, NULL);
clan_ids[i++] = atoi(data);
}
Sql_FreeResult( sql_handle );
// If we didnt load a row as expected
amount = i;
for( i = 0; i < amount; i++ ){
inter_clan_fromsql( clan_ids[i] );
}
aFree(clan_ids);
for( int32 clan_id : clan_ids ){
inter_clan_fromsql( clan_id );
}
return 0;
}
void inter_clan_final(){
db_destroy(clan_db);
clan_db.clear();
}

View File

@@ -3,6 +3,9 @@
#include "int_guild.hpp"
#include <memory>
#include <unordered_map>
#include <stdlib.h>
#define __STDC_WANT_LIB_EXT1__ 1
#include <string.h>
@@ -34,32 +37,29 @@ using namespace rathena;
static const char dataToHex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
//Guild cache
static DBMap* guild_db_; // int guild_id -> struct guild*
static DBMap *castle_db;
// int guild_id -> struct guild*
static std::unordered_map<int32, std::shared_ptr<struct guild>> guild_db;
static std::unordered_map<int32, std::shared_ptr<struct guild_castle>> castle_db;
int mapif_parse_GuildLeave(int fd,int guild_id,uint32 account_id,uint32 char_id,int flag,const char *mes);
int mapif_guild_broken(int guild_id,int flag);
bool guild_check_empty(struct guild *g);
int guild_calcinfo(struct guild *g);
bool guild_check_empty( std::shared_ptr<struct guild> g );
int guild_calcinfo( std::shared_ptr<struct guild> g );
int mapif_guild_basicinfochanged(int guild_id,int type,const void *data,int len);
int mapif_guild_info(int fd,struct guild *g);
int guild_break_sub(int key,void *data,va_list ap);
int inter_guild_tosql(struct guild *g,int flag);
int guild_checkskill(struct guild *g, int id);
int mapif_guild_info( int fd, std::shared_ptr<struct guild> g );
int inter_guild_tosql( std::shared_ptr<struct guild> g, int flag );
int guild_checkskill( std::shared_ptr<struct guild> g, int id );
TIMER_FUNC(guild_save_timer){
static int last_id = 0; //To know in which guild we were.
int state = 0; //0: Have not reached last guild. 1: Reached last guild, ready for save. 2: Some guild saved, don't do further saving.
DBIterator *iter = db_iterator(guild_db_);
DBKey key;
struct guild* g;
if( last_id == 0 ) //Save the first guild in the list.
state = 1;
for( g = (struct guild*)db_data2ptr(iter->first(iter, &key)); dbi_exists(iter); g = (struct guild*)db_data2ptr(iter->next(iter, &key)) )
{
for( auto it = guild_db.begin(); it != guild_db.end(); ){
std::shared_ptr<struct guild> g = it->second;
if( state == 0 && g->guild_id == last_id )
state++; //Save next guild in the list.
else if( state == 1 && g->save_flag&GS_MASK )
@@ -72,19 +72,20 @@ TIMER_FUNC(guild_save_timer){
state++;
}
if( g->save_flag == GS_REMOVE )
{// Nothing to save, guild is ready for removal.
// Nothing to save, guild is ready for removal.
if( g->save_flag == GS_REMOVE ){
if (charserv_config.save_log)
ShowInfo("Guild Unloaded (%d - %s)\n", g->guild_id, g->name);
db_remove(guild_db_, key);
it = guild_db.erase( it );
}else{
it++;
}
}
dbi_destroy(iter);
if( state != 2 ) //Reached the end of the guild db without saving.
last_id = 0; //Reset guild saved, return to beginning.
state = guild_db_->size(guild_db_);
state = guild_db.size();
if( state < 1 ) state = 1; //Calculate the time slot for the next save.
add_timer(tick + (charserv_config.autosave_interval)/state, guild_save_timer, 0, 0);
return 0;
@@ -100,8 +101,7 @@ int inter_guild_removemember_tosql(uint32 char_id)
}
// Save guild into sql
int inter_guild_tosql(struct guild *g,int flag)
{
int inter_guild_tosql( std::shared_ptr<struct guild> g, int flag ){
// Table guild (GS_BASIC_MASK)
// GS_EMBLEM `emblem_len`,`emblem_id`,`emblem_data`
// GS_CONNECT `connect_member`,`average_lv`
@@ -333,20 +333,21 @@ int inter_guild_tosql(struct guild *g,int flag)
}
// Read guild from sql
struct guild * inter_guild_fromsql(int guild_id)
{
struct guild *g;
std::shared_ptr<struct guild> inter_guild_fromsql( int32 guild_id ){
char* data;
size_t len;
char* p;
int i;
if( guild_id <= 0 )
return NULL;
if( guild_id <= 0 ){
return nullptr;
}
g = (struct guild*)idb_get(guild_db_, guild_id);
if( g )
std::shared_ptr<struct guild> g = util::umap_find( guild_db, guild_id );
if( g != nullptr ){
return g;
}
#ifdef NOISY
ShowInfo("Guild load request (%d)...\n", guild_id);
@@ -356,13 +357,15 @@ struct guild * inter_guild_fromsql(int guild_id)
"FROM `%s` g LEFT JOIN `%s` c ON c.`char_id` = g.`char_id` WHERE g.`guild_id`='%d'", schema_config.guild_db, schema_config.char_db, guild_id) )
{
Sql_ShowDebug(sql_handle);
return NULL;
return nullptr;
}
if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
return NULL;// Guild does not exists.
// Guild does not exists.
if( SQL_SUCCESS != Sql_NextRow( sql_handle ) ){
return nullptr;
}
CREATE(g, struct guild, 1);
g = std::make_shared<struct guild>();
g->guild_id = guild_id;
Sql_GetData(sql_handle, 0, &data, &len); memcpy(g->name, data, zmin(len, NAME_LENGTH));
@@ -412,8 +415,7 @@ struct guild * inter_guild_fromsql(int guild_id)
"FROM `%s` `m` INNER JOIN `%s` `c` on `c`.`char_id`=`m`.`char_id` WHERE `m`.`guild_id`='%d' ORDER BY `position`", schema_config.guild_member_db, schema_config.char_db, guild_id) )
{
Sql_ShowDebug(sql_handle);
aFree(g);
return NULL;
return nullptr;
}
for( i = 0; i < g->max_member && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i )
{
@@ -452,8 +454,7 @@ struct guild * inter_guild_fromsql(int guild_id)
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `position`,`name`,`mode`,`exp_mode` FROM `%s` WHERE `guild_id`='%d'", schema_config.guild_position_db, guild_id) )
{
Sql_ShowDebug(sql_handle);
aFree(g);
return NULL;
return nullptr;
}
while( SQL_SUCCESS == Sql_NextRow(sql_handle) )
{
@@ -474,8 +475,7 @@ struct guild * inter_guild_fromsql(int guild_id)
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `opposition`,`alliance_id`,`name` FROM `%s` WHERE `guild_id`='%d'", schema_config.guild_alliance_db, guild_id) )
{
Sql_ShowDebug(sql_handle);
aFree(g);
return NULL;
return nullptr;
}
for( i = 0; i < MAX_GUILDALLIANCE && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i )
{
@@ -490,8 +490,7 @@ struct guild * inter_guild_fromsql(int guild_id)
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name`,`mes` FROM `%s` WHERE `guild_id`='%d'", schema_config.guild_expulsion_db, guild_id) )
{
Sql_ShowDebug(sql_handle);
aFree(g);
return NULL;
return nullptr;
}
for( i = 0; i < MAX_GUILDEXPULSION && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i )
{
@@ -506,8 +505,7 @@ struct guild * inter_guild_fromsql(int guild_id)
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`,`lv` FROM `%s` WHERE `guild_id`='%d' ORDER BY `id`", schema_config.guild_skill_db, guild_id) )
{
Sql_ShowDebug(sql_handle);
aFree(g);
return NULL;
return nullptr;
}
for(i = 0; i < MAX_GUILDSKILL; i++)
@@ -525,8 +523,11 @@ struct guild * inter_guild_fromsql(int guild_id)
}
Sql_FreeResult(sql_handle);
idb_put(guild_db_, guild_id, g); //Add to cache
g->save_flag |= GS_REMOVE; //But set it to be removed, in case it is not needed for long.
// Add to cache
guild_db[g->guild_id] = g;
// But set it to be removed, in case it is not needed for long.
g->save_flag |= GS_REMOVE;
if (charserv_config.save_log)
ShowInfo("Guild loaded (%d - %s)\n", guild_id, g->name);
@@ -542,10 +543,10 @@ struct guild * inter_guild_fromsql(int guild_id)
uint16 inter_guild_storagemax(int guild_id)
{
#ifdef OFFICIAL_GUILD_STORAGE
struct guild *g = inter_guild_fromsql(guild_id);
std::shared_ptr<struct guild> g = inter_guild_fromsql( guild_id );
uint16 max = 0;
if (!g) {
if( g == nullptr ){
ShowError("Guild %d not found!\n", guild_id);
return 0;
}
@@ -561,8 +562,7 @@ uint16 inter_guild_storagemax(int guild_id)
}
// `guild_castle` (`castle_id`, `guild_id`, `economy`, `defense`, `triggerE`, `triggerD`, `nextTime`, `payTime`, `createTime`, `visibleC`, `visibleG0`, `visibleG1`, `visibleG2`, `visibleG3`, `visibleG4`, `visibleG5`, `visibleG6`, `visibleG7`)
int inter_guildcastle_tosql(struct guild_castle *gc)
{
int inter_guildcastle_tosql( std::shared_ptr<struct guild_castle> gc ){
StringBuf buf;
int i;
@@ -584,15 +584,16 @@ int inter_guildcastle_tosql(struct guild_castle *gc)
}
// Read guild_castle from SQL
struct guild_castle* inter_guildcastle_fromsql(int castle_id)
{
std::shared_ptr<struct guild_castle> inter_guildcastle_fromsql( int castle_id ){
char *data;
int i;
StringBuf buf;
struct guild_castle *gc = (struct guild_castle *)idb_get(castle_db, castle_id);
if (gc != NULL)
std::shared_ptr<struct guild_castle> gc = util::umap_find( castle_db, castle_id );
if( gc != nullptr ){
return gc;
}
StringBuf_Init(&buf);
StringBuf_AppendStr(&buf, "SELECT `castle_id`, `guild_id`, `economy`, `defense`, `triggerE`, "
@@ -607,7 +608,8 @@ struct guild_castle* inter_guildcastle_fromsql(int castle_id)
}
StringBuf_Destroy(&buf);
CREATE(gc, struct guild_castle, 1);
gc = std::make_shared<struct guild_castle>();
gc->castle_id = castle_id;
if (SQL_SUCCESS == Sql_NextRow(sql_handle)) {
@@ -626,7 +628,7 @@ struct guild_castle* inter_guildcastle_fromsql(int castle_id)
}
Sql_FreeResult(sql_handle);
idb_put(castle_db, castle_id, gc);
castle_db[gc->castle_id] = gc;
if (charserv_config.save_log)
ShowInfo("Loaded guild castle (%d - guild %d)\n", castle_id, gc->guild_id);
@@ -637,7 +639,6 @@ struct guild_castle* inter_guildcastle_fromsql(int castle_id)
int inter_guild_CharOnline(uint32 char_id, int guild_id)
{
struct guild *g;
int i;
if (guild_id == -1) {
@@ -664,8 +665,9 @@ int inter_guild_CharOnline(uint32 char_id, int guild_id)
if (guild_id == 0)
return 0; //No guild...
g = inter_guild_fromsql(guild_id);
if(!g) {
std::shared_ptr<struct guild> g = inter_guild_fromsql( guild_id );
if( g == nullptr ){
ShowError("Character %d's guild %d not found!\n", char_id, guild_id);
return 0;
}
@@ -687,7 +689,6 @@ int inter_guild_CharOnline(uint32 char_id, int guild_id)
int inter_guild_CharOffline(uint32 char_id, int guild_id)
{
struct guild *g=NULL;
int online_count, i;
if (guild_id == -1)
@@ -716,9 +717,12 @@ int inter_guild_CharOffline(uint32 char_id, int guild_id)
return 0; //No guild...
//Character has a guild, set character offline and check if they were the only member online
g = inter_guild_fromsql(guild_id);
if (g == NULL) //Guild not found?
std::shared_ptr<struct guild> g = inter_guild_fromsql( guild_id );
// Guild not found?
if( g == nullptr ){
return 0;
}
//Set member offline
ARR_FIND( 0, g->max_member, i, g->member[i].char_id == char_id );
@@ -800,33 +804,22 @@ void GuildExpDatabase::loadingFinished() {
// Initialize guild sql and read exp_guild.yml
void inter_guild_sql_init(void) {
//Initialize the guild cache
guild_db_= idb_alloc(DB_OPT_RELEASE_DATA);
castle_db = idb_alloc(DB_OPT_RELEASE_DATA);
guild_exp_db.load();
add_timer_func_list(guild_save_timer, "guild_save_timer");
add_timer(gettick() + 10000, guild_save_timer, 0, 0);
}
/**
* @see DBApply
*/
int guild_db_final(DBKey key, DBData *data, va_list ap)
{
struct guild *g = (struct guild*)db_data2ptr(data);
if (g->save_flag&GS_MASK) {
inter_guild_tosql(g, g->save_flag&GS_MASK);
return 1;
}
return 0;
}
void inter_guild_sql_final(void)
{
guild_db_->destroy(guild_db_, guild_db_final);
db_destroy(castle_db);
return;
for( const auto& pair : guild_db ){
std::shared_ptr<struct guild> guild = pair.second;
if( guild->save_flag&GS_MASK ){
inter_guild_tosql( guild, guild->save_flag&GS_MASK );
}
}
guild_db.clear();
castle_db.clear();
}
// Get guild_id by its name. Returns 0 if not found, -1 on error.
@@ -859,8 +852,7 @@ int search_guildname(char *str)
}
// Check if guild is empty
bool guild_check_empty(struct guild *g)
{
bool guild_check_empty( std::shared_ptr<struct guild> g ){
int i;
ARR_FIND( 0, g->max_member, i, g->member[i].account_id > 0 );
//Let the calling function handle the guild removal in case they need
@@ -874,14 +866,12 @@ t_exp GuildExpDatabase::get_nextexp(uint16 level) {
return ((guild_exp == nullptr) ? 0 : guild_exp->exp);
}
int guild_checkskill(struct guild *g,int id)
{
int guild_checkskill( std::shared_ptr<struct guild> g, int id ){
int idx = id - GD_SKILLBASE;
return idx < 0 || idx >= MAX_GUILDSKILL ? 0 : g->skill[idx].lv;
}
int guild_calcinfo(struct guild *g)
{
int guild_calcinfo( std::shared_ptr<struct guild> g ){
int i,c;
struct guild before = *g; // Save guild current values
@@ -943,8 +933,7 @@ int guild_calcinfo(struct guild *g)
//-------------------------------------------------------------------
// Packet sent to map server
int mapif_guild_created(int fd,uint32 account_id,struct guild *g)
{
int mapif_guild_created( int fd, uint32 account_id, std::shared_ptr<struct guild> g ){
WFIFOHEAD(fd, 10);
WFIFOW(fd,0)=0x3830;
WFIFOL(fd,2)=account_id;
@@ -975,12 +964,11 @@ int mapif_guild_noinfo(int fd,int guild_id)
}
// Send guild info
int mapif_guild_info(int fd,struct guild *g)
{
int mapif_guild_info( int fd, std::shared_ptr<struct guild> g ){
unsigned char buf[8+sizeof(struct guild)];
WBUFW(buf,0)=0x3831;
WBUFW(buf,2)=4+sizeof(struct guild);
memcpy(buf+4,g,sizeof(struct guild));
memcpy( buf + 4, g.get(), sizeof( struct guild ) );
if(fd<0)
chmapif_sendall(buf,WBUFW(buf,2));
else
@@ -1018,8 +1006,7 @@ int mapif_guild_withdraw(int guild_id,uint32 account_id,uint32 char_id,int flag,
}
// Send short member's info
int mapif_guild_memberinfoshort(struct guild *g,int idx)
{
int mapif_guild_memberinfoshort( std::shared_ptr<struct guild> g, int idx ){
unsigned char buf[19];
WBUFW(buf, 0)=0x3835;
WBUFL(buf, 2)=g->guild_id;
@@ -1120,8 +1107,7 @@ int mapif_guild_alliance(int guild_id1,int guild_id2,uint32 account_id1,uint32 a
}
// Send a guild position desc
int mapif_guild_position(struct guild *g,int idx)
{
int mapif_guild_position( std::shared_ptr<struct guild> g, int idx ){
unsigned char buf[12 + sizeof(struct guild_position)];
WBUFW(buf,0)=0x383b;
WBUFW(buf,2)=sizeof(struct guild_position)+12;
@@ -1133,8 +1119,7 @@ int mapif_guild_position(struct guild *g,int idx)
}
// Send the guild notice
int mapif_guild_notice(struct guild *g)
{
int mapif_guild_notice( std::shared_ptr<struct guild> g ){
unsigned char buf[256];
WBUFW(buf,0)=0x383e;
WBUFL(buf,2)=g->guild_id;
@@ -1145,8 +1130,7 @@ int mapif_guild_notice(struct guild *g)
}
// Send emblem data
int mapif_guild_emblem(struct guild *g)
{
int mapif_guild_emblem( std::shared_ptr<struct guild> g ){
unsigned char buf[12 + sizeof(g->emblem_data)];
WBUFW(buf,0)=0x383f;
WBUFW(buf,2)=g->emblem_len+12;
@@ -1158,8 +1142,7 @@ int mapif_guild_emblem(struct guild *g)
}
// Send the guild emblem_id (version)
int mapif_guild_emblem_version(guild* g)
{
int mapif_guild_emblem_version( std::shared_ptr<struct guild> g ){
unsigned char buf[10];
WBUFW(buf, 0) = 0x3841;
WBUFL(buf, 2) = g->guild_id;
@@ -1169,8 +1152,7 @@ int mapif_guild_emblem_version(guild* g)
return 0;
}
int mapif_guild_master_changed(struct guild *g, int aid, int cid, time_t time)
{
int mapif_guild_master_changed( std::shared_ptr<struct guild> g, int aid, int cid, time_t time ){
unsigned char buf[18];
WBUFW(buf,0)=0x3843;
WBUFL(buf,2)=g->guild_id;
@@ -1183,17 +1165,16 @@ int mapif_guild_master_changed(struct guild *g, int aid, int cid, time_t time)
int mapif_guild_castle_dataload(int fd, int sz, int *castle_ids)
{
struct guild_castle *gc = NULL;
int num = (sz - 4) / sizeof(int);
int len = 4 + num * sizeof(*gc);
int len = 4 + num * sizeof( struct guild_castle );
int i;
WFIFOHEAD(fd, len);
WFIFOW(fd, 0) = 0x3840;
WFIFOW(fd, 2) = len;
for (i = 0; i < num; i++) {
gc = inter_guildcastle_fromsql(*(castle_ids++));
memcpy(WFIFOP(fd, 4 + i * sizeof(*gc)), gc, sizeof(*gc));
std::shared_ptr<struct guild_castle> gc = inter_guildcastle_fromsql( *(castle_ids++) );
memcpy( WFIFOP( fd, 4 + i * sizeof( struct guild_castle ) ), gc.get(), sizeof( struct guild_castle ) );
}
WFIFOSET(fd, len);
return 0;
@@ -1206,7 +1187,6 @@ int mapif_guild_castle_dataload(int fd, int sz, int *castle_ids)
// Guild creation request
int mapif_parse_CreateGuild(int fd,uint32 account_id,char *name,struct guild_member *master)
{
struct guild *g;
int i=0;
#ifdef NOISY
ShowInfo("Creating Guild (%s)\n", name);
@@ -1231,8 +1211,9 @@ int mapif_parse_CreateGuild(int fd,uint32 account_id,char *name,struct guild_mem
}
}
g = (struct guild *)aMalloc(sizeof(struct guild));
memset(g,0,sizeof(struct guild));
std::shared_ptr<struct guild> g = std::make_shared<struct guild>();
memset( g.get(), 0, sizeof( struct guild ) );
memcpy(g->name,name,NAME_LENGTH);
memcpy(g->master,master->name,NAME_LENGTH);
@@ -1263,13 +1244,12 @@ int mapif_parse_CreateGuild(int fd,uint32 account_id,char *name,struct guild_mem
//Failed to Create guild....
ShowError("Failed to create Guild %s (Guild Master: %s)\n", g->name, g->master);
mapif_guild_created(fd,account_id,NULL);
aFree(g);
return 0;
}
ShowInfo("Created Guild %d - %s (Guild Master: %s)\n", g->guild_id, g->name, g->master);
//Add to cache
idb_put(guild_db_, g->guild_id, g);
// Add to cache
guild_db[g->guild_id] = g;
// Report to client
mapif_guild_created(fd,account_id,g);
@@ -1285,13 +1265,12 @@ int mapif_parse_CreateGuild(int fd,uint32 account_id,char *name,struct guild_mem
// Return guild info to client
int mapif_parse_GuildInfo(int fd,int guild_id)
{
struct guild * g = inter_guild_fromsql(guild_id); //We use this because on start-up the info of castle-owned guilds is requied. [Skotlex]
if(g)
{
std::shared_ptr<struct guild> g = inter_guild_fromsql( guild_id );
if( g != nullptr ){
if (!guild_calcinfo(g))
mapif_guild_info(fd,g);
}
else
}else
mapif_guild_noinfo(fd,guild_id); // Failed to load info
return 0;
}
@@ -1299,19 +1278,16 @@ int mapif_parse_GuildInfo(int fd,int guild_id)
// Add member to guild
int mapif_parse_GuildAddMember(int fd,int guild_id,struct guild_member *m)
{
struct guild * g;
int i;
std::shared_ptr<struct guild> g = inter_guild_fromsql( guild_id );
g = inter_guild_fromsql(guild_id);
if(g==NULL){
if( g == nullptr ){
// Failed to add
mapif_guild_memberadded(fd,guild_id,m->account_id,m->char_id,1);
return 0;
}
// Find an empty slot
for(i=0;i<g->max_member;i++)
{
for( int i = 0; i < g->max_member; i++ ){
if(g->member[i].account_id==0)
{
memcpy(&g->member[i],m,sizeof(struct guild_member));
@@ -1337,9 +1313,9 @@ int mapif_parse_GuildLeave(int fd, int guild_id, uint32 account_id, uint32 char_
{
int i;
struct guild* g = inter_guild_fromsql(guild_id);
if( g == NULL )
{
std::shared_ptr<struct guild> g = inter_guild_fromsql( guild_id );
if( g == nullptr ){
// Unknown guild, just update the player
if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `guild_id`='0' WHERE `account_id`='%d' AND `char_id`='%d'", schema_config.char_db, account_id, char_id) )
Sql_ShowDebug(sql_handle);
@@ -1394,13 +1370,14 @@ int mapif_parse_GuildLeave(int fd, int guild_id, uint32 account_id, uint32 char_
int mapif_parse_GuildChangeMemberInfoShort(int fd,int guild_id,uint32 account_id,uint32 char_id,int online,int lv,int class_)
{
// Could speed up by manipulating only guild_member
struct guild * g;
int i,sum,c;
int prev_count, prev_alv;
g = inter_guild_fromsql(guild_id);
if(g==NULL)
std::shared_ptr<struct guild> g = inter_guild_fromsql( guild_id );
if( g == nullptr ){
return 0;
}
ARR_FIND( 0, g->max_member, i, g->member[i].account_id == account_id && g->member[i].char_id == char_id );
if( i < g->max_member )
@@ -1446,11 +1423,11 @@ int mapif_parse_GuildChangeMemberInfoShort(int fd,int guild_id,uint32 account_id
// BreakGuild
int mapif_parse_BreakGuild(int fd,int guild_id)
{
struct guild * g;
std::shared_ptr<struct guild> g = inter_guild_fromsql( guild_id );
g = inter_guild_fromsql(guild_id);
if(g==NULL)
if( g == nullptr ){
return 0;
}
// Delete guild from sql
//printf("- Delete guild %d from guild\n",guild_id);
@@ -1487,8 +1464,9 @@ int mapif_parse_BreakGuild(int fd,int guild_id)
if(charserv_config.log_inter)
inter_log("guild %s (id=%d) broken\n",g->name,guild_id);
//Remove the guild from memory. [Skotlex]
idb_remove(guild_db_, guild_id);
// Remove the guild from memory. [Skotlex]
guild_db.erase( guild_id );
return 0;
}
@@ -1501,10 +1479,11 @@ int mapif_parse_GuildMessage(int fd,int guild_id,uint32 account_id,char *mes,int
// Modification of the guild
int mapif_parse_GuildBasicInfoChange(int fd,int guild_id,int type,const char *data,int len)
{
struct guild *g = inter_guild_fromsql(guild_id);
std::shared_ptr<struct guild> g = inter_guild_fromsql( guild_id );
if (!g)
if( g == nullptr ){
return 0;
}
short data_value = *((short *)data);
@@ -1542,11 +1521,12 @@ int mapif_parse_GuildMemberInfoChange(int fd,int guild_id,uint32 account_id,uint
{
// Could make some improvement in speed, because only change guild_member
int i;
struct guild * g;
g = inter_guild_fromsql(guild_id);
if(g==NULL)
std::shared_ptr<struct guild> g = inter_guild_fromsql( guild_id );
if( g == nullptr ){
return 0;
}
// Search the member
for(i=0;i<g->max_member;i++)
@@ -1649,12 +1629,11 @@ int inter_guild_sex_changed(int guild_id,uint32 account_id,uint32 char_id, short
int inter_guild_charname_changed(int guild_id,uint32 account_id, uint32 char_id, char *name)
{
struct guild *g;
int i, flag = 0;
g = inter_guild_fromsql(guild_id);
if( g == NULL )
{
std::shared_ptr<struct guild> g = inter_guild_fromsql( guild_id );
if( g == nullptr ){
ShowError("inter_guild_charrenamed: Can't find guild %d.\n", guild_id);
return 0;
}
@@ -1687,11 +1666,11 @@ int inter_guild_charname_changed(int guild_id,uint32 account_id, uint32 char_id,
int mapif_parse_GuildPosition(int fd,int guild_id,int idx,struct guild_position *p)
{
// Could make some improvement in speed, because only change guild_position
struct guild * g;
std::shared_ptr<struct guild> g = inter_guild_fromsql( guild_id );
g = inter_guild_fromsql(guild_id);
if(g==NULL || idx<0 || idx>=MAX_GUILDPOSITION)
if( g == nullptr || idx < 0 || idx >= MAX_GUILDPOSITION ){
return 0;
}
memcpy(&g->position[idx],p,sizeof(struct guild_position));
mapif_guild_position(g,idx);
@@ -1703,12 +1682,13 @@ int mapif_parse_GuildPosition(int fd,int guild_id,int idx,struct guild_position
// Guild Skill UP
int mapif_parse_GuildSkillUp(int fd,int guild_id,uint16 skill_id,uint32 account_id,int max)
{
struct guild * g;
int idx = skill_id - GD_SKILLBASE;
g = inter_guild_fromsql(guild_id);
if(g == NULL || idx < 0 || idx >= MAX_GUILDSKILL)
std::shared_ptr<struct guild> g = inter_guild_fromsql( guild_id );
if( g == nullptr || idx < 0 || idx >= MAX_GUILDSKILL ){
return 0;
}
if(g->skill_point>0 && g->skill[idx].id>0 && g->skill[idx].lv<max )
{
@@ -1725,8 +1705,7 @@ int mapif_parse_GuildSkillUp(int fd,int guild_id,uint16 skill_id,uint32 account_
}
//Manual deletion of an alliance when partnering guild does not exists. [Skotlex]
int mapif_parse_GuildDeleteAlliance(struct guild *g, int guild_id, uint32 account_id1, uint32 account_id2, int flag)
{
int mapif_parse_GuildDeleteAlliance( std::shared_ptr<struct guild> g, int guild_id, uint32 account_id1, uint32 account_id2, int flag ){
int i;
char name[NAME_LENGTH];
@@ -1755,16 +1734,19 @@ int mapif_parse_GuildDeleteAlliance(struct guild *g, int guild_id, uint32 accoun
int mapif_parse_GuildAlliance(int fd,int guild_id1,int guild_id2,uint32 account_id1,uint32 account_id2,int flag)
{
// Could speed up
struct guild *g[2];
std::shared_ptr<struct guild> g[2];
int j,i;
g[0] = inter_guild_fromsql(guild_id1);
g[1] = inter_guild_fromsql(guild_id2);
if(g[0] && g[1]==NULL && (flag & GUILD_ALLIANCE_REMOVE)) //Requested to remove an alliance with a not found guild.
// Requested to remove an alliance with a not found guild.
if( g[0] != nullptr && g[1] == nullptr && ( flag & GUILD_ALLIANCE_REMOVE ) ){
return mapif_parse_GuildDeleteAlliance(g[0], guild_id2, account_id1, account_id2, flag); //Try to do a manual removal of said guild.
}
if(g[0]==NULL || g[1]==NULL)
if( g[0] == nullptr || g[1] == nullptr ){
return 0;
}
if(flag&GUILD_ALLIANCE_REMOVE)
{
@@ -1805,11 +1787,11 @@ int mapif_parse_GuildAlliance(int fd,int guild_id1,int guild_id2,uint32 account_
// Change guild message
int mapif_parse_GuildNotice(int fd,int guild_id,const char *mes1,const char *mes2)
{
struct guild *g;
std::shared_ptr<struct guild> g = inter_guild_fromsql( guild_id );
g = inter_guild_fromsql(guild_id);
if(g==NULL)
if( g == nullptr ){
return 0;
}
memcpy(g->mes1,mes1,MAX_GUILDMES1);
memcpy(g->mes2,mes2,MAX_GUILDMES2);
@@ -1820,11 +1802,11 @@ int mapif_parse_GuildNotice(int fd,int guild_id,const char *mes1,const char *mes
int mapif_parse_GuildEmblem(int fd,int len,int guild_id,int dummy,const char *data)
{
struct guild * g;
std::shared_ptr<struct guild> g = inter_guild_fromsql( guild_id );
g = inter_guild_fromsql(guild_id);
if(g==NULL)
if( g == nullptr ){
return 0;
}
if (len > sizeof(g->emblem_data))
len = sizeof(g->emblem_data);
@@ -1843,9 +1825,9 @@ int mapif_parse_GuildCastleDataLoad(int fd, int len, int *castle_ids)
int mapif_parse_GuildCastleDataSave(int fd, int castle_id, int index, int value)
{
struct guild_castle *gc = inter_guildcastle_fromsql(castle_id);
std::shared_ptr<struct guild_castle> gc = inter_guildcastle_fromsql( castle_id );
if (gc == NULL) {
if( gc == nullptr ){
ShowError("mapif_parse_GuildCastleDataSave: castle id=%d not found\n", castle_id);
return 0;
}
@@ -1854,7 +1836,7 @@ int mapif_parse_GuildCastleDataSave(int fd, int castle_id, int index, int value)
case CD_GUILD_ID:
if (charserv_config.log_inter && gc->guild_id != value) {
int gid = (value) ? value : gc->guild_id;
struct guild *g = (struct guild*)idb_get(guild_db_, gid);
std::shared_ptr<struct guild> g = util::umap_find( guild_db, gid );
inter_log("guild %s (id=%d) %s castle id=%d\n",
(g) ? g->name : "??", gid, (value) ? "occupy" : "abandon", castle_id);
}
@@ -1882,14 +1864,14 @@ int mapif_parse_GuildCastleDataSave(int fd, int castle_id, int index, int value)
int mapif_parse_GuildMasterChange(int fd, int guild_id, const char* name, int len)
{
struct guild * g;
struct guild_member gm;
int pos;
g = inter_guild_fromsql(guild_id);
std::shared_ptr<struct guild> g = inter_guild_fromsql( guild_id );
if(g==NULL || len > NAME_LENGTH)
if( g == nullptr || len > NAME_LENGTH ){
return 0;
}
// Find member (name)
for (pos = 0; pos < g->max_member && strncmp(g->member[pos].name, name, len); pos++);
@@ -1922,7 +1904,7 @@ int mapif_parse_GuildMasterChange(int fd, int guild_id, const char* name, int le
int mapif_parse_GuildEmblemVersion(int fd, int guild_id, int version)
{
guild* g = inter_guild_fromsql(guild_id);
std::shared_ptr<struct guild> g = inter_guild_fromsql( guild_id );
if (g == nullptr)
return 0;

View File

@@ -3,6 +3,8 @@
#include "int_mail.hpp"
#include <memory>
#include <stdlib.h>
#include <string.h>
@@ -11,11 +13,14 @@
#include "../common/socket.hpp"
#include "../common/sql.hpp"
#include "../common/strlib.hpp"
#include "../common/utilities.hpp"
#include "char.hpp"
#include "char_mapif.hpp"
#include "inter.hpp"
using namespace rathena;
bool mail_loadmessage(int mail_id, struct mail_message* msg);
void mapif_Mail_return( int fd, uint32 char_id, int mail_id, uint32 account_id_receiver = 0, uint32 account_id_sender = 0 );
bool mapif_Mail_delete( int fd, uint32 char_id, int mail_id, uint32 account_id = 0 );
@@ -460,10 +465,10 @@ bool mapif_Mail_delete( int fd, uint32 char_id, int mail_id, uint32 account_id )
// If the char server triggered this, check if we have to notify a map server
if( fd <= 0 ){
struct online_char_data* character;
std::shared_ptr<struct online_char_data> character = util::umap_find( char_get_onlinedb(), account_id );
// Check for online players
if( ( character = (struct online_char_data*)idb_get( char_get_onlinedb(), account_id ) ) != nullptr && character->server >= 0 ){
if( character != nullptr && character->server >= 0 ){
fd = map_server[character->server].fd;
}else{
// The request was triggered inside the character server or the player is offline now
@@ -561,10 +566,10 @@ void mapif_Mail_return( int fd, uint32 char_id, int mail_id, uint32 account_id_r
// If the char server triggered this, check if we have to notify a map server
if( fd <= 0 ){
struct online_char_data* character;
std::shared_ptr<struct online_char_data> character = util::umap_find( char_get_onlinedb(), account_id_sender );
// Check for online players
if( ( character = (struct online_char_data*)idb_get( char_get_onlinedb(), account_id_sender ) ) != nullptr && character->server >= 0 ){
if( character != nullptr && character->server >= 0 ){
fd = map_server[character->server].fd;
}else{
// The request was triggered inside the character server or the player is offline now

View File

@@ -3,6 +3,9 @@
#include "int_party.hpp"
#include <memory>
#include <unordered_map>
#include <stdlib.h>
#include <string.h>
@@ -14,11 +17,14 @@
#include "../common/socket.hpp"
#include "../common/sql.hpp"
#include "../common/strlib.hpp"
#include "../common/utilities.hpp"
#include "char.hpp"
#include "char_mapif.hpp"
#include "inter.hpp"
using namespace rathena;
struct party_data {
struct party party;
unsigned int min_lv, max_lv;
@@ -26,18 +32,18 @@ struct party_data {
unsigned char size; //Total size of party.
};
static struct party_data *party_pt;
static DBMap* party_db_; // int party_id -> struct party_data*
// int party_id -> struct party_data*
static std::unordered_map<int32, std::shared_ptr<struct party_data>> party_db;
int mapif_party_broken(int party_id,int flag);
int party_check_empty(struct party_data *p);
int party_check_empty( std::shared_ptr<struct party_data> p );
int mapif_parse_PartyLeave(int fd, int party_id, uint32 account_id, uint32 char_id, char *name, enum e_party_member_withdraw type);
int party_check_exp_share(struct party_data *p);
int party_check_exp_share( std::shared_ptr<struct party_data> p );
int mapif_party_optionchanged(int fd,struct party *p, uint32 account_id, int flag);
int party_check_family_share(struct party_data *p);
int party_check_family_share( std::shared_ptr<struct party_data> p );
//Updates party's level range and unsets even share if broken.
static int int_party_check_lv(struct party_data *p) {
static int int_party_check_lv( std::shared_ptr<struct party_data> p ){
int i;
unsigned int lv;
p->min_lv = UINT_MAX;
@@ -62,8 +68,7 @@ static int int_party_check_lv(struct party_data *p) {
return 1;
}
//Calculates the state of a party.
void int_party_calc_state(struct party_data *p)
{
void int_party_calc_state( std::shared_ptr<struct party_data> p ){
int i;
p->min_lv = UINT_MAX;
p->max_lv = 0;
@@ -116,7 +121,7 @@ int inter_party_tosql(struct party *p, int flag, int index)
{
// 'party' ('party_id','name','exp','item','leader_id','leader_char')
char esc_name[NAME_LENGTH*2+1];// escaped party name
int party_id;
int32 party_id;
if( p == NULL || p->party_id == 0 )
return 0;
@@ -135,7 +140,7 @@ int inter_party_tosql(struct party *p, int flag, int index)
if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `party_id`='%d'", schema_config.party_db, party_id) )
Sql_ShowDebug(sql_handle);
//Remove from memory
idb_remove(party_db_, party_id);
party_db.erase( party_id );
return 1;
}
@@ -186,11 +191,9 @@ int inter_party_tosql(struct party *p, int flag, int index)
}
// Read party from mysql
struct party_data *inter_party_fromsql(int party_id)
{
std::shared_ptr<struct party_data> inter_party_fromsql( int party_id ){
int leader_id = 0;
int leader_char = 0;
struct party_data* p;
struct party_member* m;
char* data;
size_t len;
@@ -203,12 +206,11 @@ struct party_data *inter_party_fromsql(int party_id)
return NULL;
//Load from memory
p = (struct party_data*)idb_get(party_db_, party_id);
if( p != NULL )
return p;
std::shared_ptr<struct party_data> p = util::umap_find( party_db, party_id );
p = party_pt;
memset(p, 0, sizeof(struct party_data));
if( p != nullptr ){
return p;
}
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `party_id`, `name`,`exp`,`item`, `leader_id`, `leader_char` FROM `%s` WHERE `party_id`='%d'", schema_config.party_db, party_id) )
{
@@ -219,6 +221,8 @@ struct party_data *inter_party_fromsql(int party_id)
if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
return NULL;
p = std::make_shared<struct party_data>();
p->party.party_id = party_id;
Sql_GetData(sql_handle, 1, &data, &len); memcpy(p->party.name, data, zmin(len, NAME_LENGTH));
Sql_GetData(sql_handle, 2, &data, NULL); p->party.exp = (atoi(data) ? 1 : 0);
@@ -249,47 +253,38 @@ struct party_data *inter_party_fromsql(int party_id)
if( charserv_config.save_log )
ShowInfo("Party loaded (%d - %s).\n", party_id, p->party.name);
//Add party to memory.
CREATE(p, struct party_data, 1);
memcpy(p, party_pt, sizeof(struct party_data));
//init state
int_party_calc_state(p);
idb_put(party_db_, party_id, p);
party_db[p->party.party_id] = p;
return p;
}
int inter_party_sql_init(void)
{
//memory alloc
party_db_ = idb_alloc(DB_OPT_RELEASE_DATA);
party_pt = (struct party_data*)aCalloc(sizeof(struct party_data), 1);
if (!party_pt) {
ShowFatalError("inter_party_sql_init: Out of Memory!\n");
exit(EXIT_FAILURE);
// Remove parties with no members on startup from party_db. [Skotlex]
if (charserv_config.clear_parties) {
ShowStatus("Cleaning party table...\n");
if (SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` USING `%s` LEFT JOIN `%s` ON `%s`.leader_id =`%s`.account_id AND `%s`.leader_char = `%s`.char_id WHERE `%s`.account_id IS NULL",
schema_config.party_db, schema_config.party_db, schema_config.char_db, schema_config.party_db, schema_config.char_db, schema_config.party_db, schema_config.char_db, schema_config.char_db))
Sql_ShowDebug(sql_handle);
}
/* Uncomment the following if you want to do a party_db cleanup (remove parties with no members) on startup.[Skotlex]
ShowStatus("cleaning party table...\n");
if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` USING `%s` LEFT JOIN `%s` ON `%s`.leader_id =`%s`.account_id AND `%s`.leader_char = `%s`.char_id WHERE `%s`.account_id IS NULL",
party_db, party_db, char_db, party_db, char_db, party_db, char_db, char_db) )
Sql_ShowDebug(sql_handle);
*/
return 0;
}
void inter_party_sql_final(void)
{
party_db_->destroy(party_db_, NULL);
aFree(party_pt);
return;
party_db.clear();
}
// Search for the party according to its name
struct party_data* search_partyname(char* str)
{
std::shared_ptr<struct party_data> search_partyname( char* str ){
char esc_name[NAME_LENGTH*2+1];
char* data;
struct party_data* p = NULL;
std::shared_ptr<struct party_data> p = nullptr;
Sql_EscapeStringLen(sql_handle, esc_name, str, safestrnlen(str, NAME_LENGTH));
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `party_id` FROM `%s` WHERE `name`='%s'", schema_config.party_db, esc_name) )
@@ -304,7 +299,7 @@ struct party_data* search_partyname(char* str)
return p;
}
int party_check_family_share(struct party_data *p) {
int party_check_family_share( std::shared_ptr<struct party_data> p ){
int i;
unsigned short map = 0;
if (!p->family)
@@ -340,16 +335,18 @@ int party_check_family_share(struct party_data *p) {
}
// Returns whether this party can keep having exp share or not.
int party_check_exp_share(struct party_data *p)
{
int party_check_exp_share( std::shared_ptr<struct party_data> p ){
return (p->party.count < 2 || p->max_lv - p->min_lv <= party_share_level || party_check_family_share(p));
}
// Is there any member in the party?
int party_check_empty(struct party_data *p)
{
int party_check_empty( std::shared_ptr<struct party_data> p ){
int i;
if (p==NULL||p->party.party_id==0) return 1;
if( p == nullptr || p->party.party_id == 0 ){
return 1;
}
for(i=0;i<MAX_PARTY && !p->party.member[i].account_id;i++);
if (i < MAX_PARTY) return 0;
// If there is no member, then break the party
@@ -503,15 +500,16 @@ int mapif_party_message(int party_id,uint32 account_id,char *mes,int len, int sf
// Create Party
int mapif_parse_CreateParty(int fd, char *name, int item, int item2, struct party_member *leader)
{
struct party_data *p;
int i;
if( (p=search_partyname(name))!=NULL){
std::shared_ptr<struct party_data> p = search_partyname( name );
if( p != nullptr ){
mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
return 0;
}
// Check Authorised letters/symbols in the name of the character
if (charserv_config.char_config.char_name_option == 1) { // only letters/symbols in char_name_letters are authorised
for (i = 0; i < NAME_LENGTH && name[i]; i++)
for( int i = 0; i < NAME_LENGTH && name[i]; i++ ){
if (strchr(charserv_config.char_config.char_name_letters, name[i]) == NULL) {
if( name[i] == '"' ) { /* client-special-char */
normalize_name(name,"\"");
@@ -521,15 +519,17 @@ int mapif_parse_CreateParty(int fd, char *name, int item, int item2, struct part
mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
return 0;
}
}
} else if (charserv_config.char_config.char_name_option == 2) { // letters/symbols in char_name_letters are forbidden
for (i = 0; i < NAME_LENGTH && name[i]; i++)
for( int i = 0; i < NAME_LENGTH && name[i]; i++ ){
if (strchr(charserv_config.char_config.char_name_letters, name[i]) != NULL) {
mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
return 0;
}
}
}
p = (struct party_data*)aCalloc(1, sizeof(struct party_data));
p = std::make_shared<struct party_data>();
memcpy(p->party.name,name,NAME_LENGTH);
p->party.exp=0;
@@ -543,11 +543,11 @@ int mapif_parse_CreateParty(int fd, char *name, int item, int item2, struct part
if (inter_party_tosql(&p->party,PS_CREATE|PS_ADDMEMBER,0)) {
//Add party to db
int_party_calc_state(p);
idb_put(party_db_, p->party.party_id, p);
party_db[p->party.party_id] = p;
mapif_party_info(fd, &p->party, 0);
mapif_party_created(fd,leader->account_id,leader->char_id,&p->party);
} else { //Failed to create party.
aFree(p);
}else{
// Failed to create party.
mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
}
@@ -557,22 +557,23 @@ int mapif_parse_CreateParty(int fd, char *name, int item, int item2, struct part
// Party information request
void mapif_parse_PartyInfo(int fd, int party_id, uint32 char_id)
{
struct party_data *p;
p = inter_party_fromsql(party_id);
if (p)
std::shared_ptr<struct party_data> p = inter_party_fromsql( party_id );
if( p != nullptr ){
mapif_party_info(fd, &p->party, char_id);
else
}else{
mapif_party_noinfo(fd, party_id, char_id);
}
}
// Add a player to party request
int mapif_parse_PartyAddMember(int fd, int party_id, struct party_member *member)
{
struct party_data *p;
int i;
p = inter_party_fromsql(party_id);
if( p == NULL || p->size == MAX_PARTY ) {
std::shared_ptr<struct party_data> p = inter_party_fromsql( party_id );
if( p == nullptr || p->size == MAX_PARTY ){
mapif_party_memberadded(fd, party_id, member->account_id, member->char_id, 1);
return 0;
}
@@ -606,9 +607,9 @@ int mapif_parse_PartyAddMember(int fd, int party_id, struct party_member *member
//Party setting change request
int mapif_parse_PartyChangeOption(int fd,int party_id,uint32 account_id,int exp,int item)
{
struct party_data *p;
int flag = 0;
p = inter_party_fromsql(party_id);
std::shared_ptr<struct party_data> p = inter_party_fromsql( party_id );
if(!p)
return 0;
@@ -628,12 +629,12 @@ int mapif_parse_PartyChangeOption(int fd,int party_id,uint32 account_id,int exp,
//Request leave party
int mapif_parse_PartyLeave(int fd, int party_id, uint32 account_id, uint32 char_id, char *name, enum e_party_member_withdraw type)
{
struct party_data *p;
int i,j=-1;
p = inter_party_fromsql(party_id);
if( p == NULL )
{// Party does not exists?
std::shared_ptr<struct party_data> p = inter_party_fromsql( party_id );
// Party does not exists?
if( p == nullptr ){
if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", schema_config.char_db, party_id) )
Sql_ShowDebug(sql_handle);
return 0;
@@ -680,12 +681,13 @@ int mapif_parse_PartyLeave(int fd, int party_id, uint32 account_id, uint32 char_
// When member goes to other map or levels up.
int mapif_parse_PartyChangeMap(int fd, int party_id, uint32 account_id, uint32 char_id, unsigned short map, int online, unsigned int lv)
{
struct party_data *p;
int i;
p = inter_party_fromsql(party_id);
if (p == NULL)
std::shared_ptr<struct party_data> p = inter_party_fromsql( party_id );
if( p == nullptr ){
return 0;
}
for(i = 0; i < MAX_PARTY &&
(p->party.member[i].account_id != account_id ||
@@ -738,9 +740,7 @@ int mapif_parse_PartyChangeMap(int fd, int party_id, uint32 account_id, uint32 c
//Request party dissolution
int mapif_parse_BreakParty(int fd,int party_id)
{
struct party_data *p;
p = inter_party_fromsql(party_id);
std::shared_ptr<struct party_data> p = inter_party_fromsql( party_id );
if(!p)
return 0;
@@ -757,16 +757,12 @@ int mapif_parse_PartyMessage(int fd,int party_id,uint32 account_id,char *mes,int
int mapif_parse_PartyLeaderChange(int fd,int party_id,uint32 account_id,uint32 char_id)
{
struct party_data *p;
int i;
p = inter_party_fromsql(party_id);
std::shared_ptr<struct party_data> p = inter_party_fromsql( party_id );
if(!p)
return 0;
for (i = 0; i < MAX_PARTY; i++)
{
for( int i = 0; i < MAX_PARTY; i++ ){
if(p->party.member[i].leader)
p->party.member[i].leader = 0;
if(p->party.member[i].account_id == account_id &&
@@ -787,16 +783,16 @@ int mapif_parse_PartyLeaderChange(int fd,int party_id,uint32 account_id,uint32 c
*/
int mapif_parse_PartyShareLevel(int fd,unsigned int share_lvl)
{
struct party_data *p;
DBIterator* iter = db_iterator(party_db_);
party_share_level = share_lvl;
for(p = (struct party_data *)dbi_first(iter); dbi_exists(iter); p = (struct party_data *)dbi_next(iter)) { //Update online parties
if(p->party.count > 1)
int_party_calc_state(p);
// Update online parties
for( const auto& pair : party_db ){
std::shared_ptr<struct party_data> p = pair.second;
if( p->party.count > 1 ){
int_party_calc_state( p );
}
}
dbi_destroy(iter);
return 1;
}
@@ -837,7 +833,6 @@ int inter_party_leave(int party_id,uint32 account_id, uint32 char_id, char *name
int inter_party_CharOnline(uint32 char_id, int party_id)
{
struct party_data* p;
int i;
if( party_id == -1 )
@@ -860,7 +855,8 @@ int inter_party_CharOnline(uint32 char_id, int party_id)
if (party_id == 0)
return 0; //No party...
p = inter_party_fromsql(party_id);
std::shared_ptr<struct party_data> p = inter_party_fromsql( party_id );
if(!p) {
ShowError("Character %d's party %d not found!\n", char_id, party_id);
return 0;
@@ -883,7 +879,6 @@ int inter_party_CharOnline(uint32 char_id, int party_id)
}
int inter_party_CharOffline(uint32 char_id, int party_id) {
struct party_data *p=NULL;
int i;
if( party_id == -1 )
@@ -907,8 +902,11 @@ int inter_party_CharOffline(uint32 char_id, int party_id) {
return 0; //No party...
//Character has a party, set character offline and check if they were the only member online
if ((p = inter_party_fromsql(party_id)) == NULL)
std::shared_ptr<struct party_data> p = inter_party_fromsql( party_id );
if( p == nullptr ){
return 0;
}
//Set member offline
for(i=0; i< MAX_PARTY; i++) {
@@ -923,20 +921,21 @@ int inter_party_CharOffline(uint32 char_id, int party_id) {
}
}
if(!p->party.count)
//Parties don't have any data that needs be saved at this point... so just remove it from memory.
idb_remove(party_db_, party_id);
// Parties don't have any data that needs be saved at this point... so just remove it from memory.
if( p->party.count == 0 ){
party_db.erase( party_id );
}
return 1;
}
int inter_party_charname_changed(int party_id, uint32 char_id, char *name)
{
struct party_data* p = NULL;
int i;
p = inter_party_fromsql(party_id);
if( p == NULL || p->party.party_id == 0 )
{
std::shared_ptr<struct party_data> p = inter_party_fromsql( party_id );
if( p == nullptr || p->party.party_id == 0 ){
ShowError("inter_party_charname_changed: Can't find party %d.\n", party_id);
return 0;
}

View File

@@ -3,11 +3,14 @@
#include "inter.hpp"
#include <memory>
#include <unordered_map>
#include <vector>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <sys/stat.h> // for stat/lstat/fstat - [Dekamaster/Ultimate GM Tool]
#include <vector>
#include "../common/cbasetypes.hpp"
#include "../common/database.hpp"
@@ -34,12 +37,12 @@
#include "int_quest.hpp"
#include "int_storage.hpp"
using namespace rathena;
std::string cfgFile = "inter_athena.yml"; ///< Inter-Config file
InterServerDatabase interServerDb;
#define WISDATA_TTL (60*1000) //Wis data Time To Live (60 seconds)
#define WISDELLIST_MAX 256 // Number of elements in the list Delete data Wis
Sql* sql_handle = NULL; ///Link to mysql db, connection FD
@@ -66,13 +69,18 @@ int inter_recv_packet_length[] = {
2,-1, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 30A0- Clan packets
};
#ifndef WHISPER_MESSAGE_SIZE
#define WHISPER_MESSAGE_SIZE 512
#endif
struct WisData {
int id, fd, count, len, gmlvl;
t_tick tick;
char src[NAME_LENGTH], dst[NAME_LENGTH], msg[512];
char src[NAME_LENGTH], dst[NAME_LENGTH], msg[WHISPER_MESSAGE_SIZE];
};
static DBMap* wis_db = NULL; // int wis_id -> struct WisData*
static int wis_dellist[WISDELLIST_MAX], wis_delnum;
// int wis_id -> struct WisData*
static std::unordered_map<int32, std::shared_ptr<struct WisData>> wis_db;
/* from pc.cpp due to @accinfo. any ideas to replace this crap are more than welcome. */
const char* job_name(int class_) {
@@ -405,7 +413,7 @@ void geoip_readdb(void){
ShowStatus("Finished Reading " CL_GREEN "GeoIP" CL_RESET " Database.\n");
}
/* [Dekamaster/Nightroad] */
/* WHY NOT A DBMAP: There are millions of entries in GeoIP and it has its own algorithm to go quickly through them, a DBMap wouldn't be efficient */
/* There are millions of entries in GeoIP and it has its own algorithm to go quickly through them */
const char* geoip_getcountry(uint32 ipnum){
int depth;
unsigned int x;
@@ -987,7 +995,6 @@ int inter_init_sql(const char *file)
Sql_ShowDebug(sql_handle);
}
wis_db = idb_alloc(DB_OPT_RELEASE_DATA);
interServerDb.load();
inter_guild_sql_init();
inter_storage_sql_init();
@@ -1007,7 +1014,7 @@ int inter_init_sql(const char *file)
// finalize
void inter_final(void)
{
wis_db->destroy(wis_db, NULL);
wis_db.clear();
inter_guild_sql_final();
inter_storage_sql_final();
@@ -1073,8 +1080,7 @@ int mapif_broadcast(unsigned char *mes, int len, unsigned long fontColor, short
}
// Wis sending
int mapif_wis_message(struct WisData *wd)
{
int mapif_wis_message( std::shared_ptr<struct WisData> wd ){
unsigned char buf[2048];
int headersize = 12 + 2 * NAME_LENGTH;
@@ -1116,40 +1122,19 @@ int mapif_disconnectplayer(int fd, uint32 account_id, uint32 char_id, int reason
//--------------------------------------------------------
/**
* Existence check of WISP data
* @see DBApply
*/
int check_ttl_wisdata_sub(DBKey key, DBData *data, va_list ap)
{
t_tick tick;
struct WisData *wd = (struct WisData *)db_data2ptr(data);
tick = va_arg(ap, t_tick);
if (DIFF_TICK(tick, wd->tick) > WISDATA_TTL && wis_delnum < WISDELLIST_MAX)
wis_dellist[wis_delnum++] = wd->id;
return 0;
}
int check_ttl_wisdata(void)
{
void check_ttl_wisdata(){
t_tick tick = gettick();
int i;
do {
wis_delnum = 0;
wis_db->foreach(wis_db, check_ttl_wisdata_sub, tick);
for(i = 0; i < wis_delnum; i++) {
struct WisData *wd = (struct WisData*)idb_get(wis_db, wis_dellist[i]);
ShowWarning("inter: wis data id=%d time out : from %s to %s\n", wd->id, wd->src, wd->dst);
// removed. not send information after a timeout. Just no answer for the player
//mapif_wis_reply(wd->fd, wd->src, 1); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
idb_remove(wis_db, wd->id);
for( auto it = wis_db.begin(); it != wis_db.end(); ){
std::shared_ptr<struct WisData> wd = it->second;
if( DIFF_TICK( tick, wd->tick ) > WISDATA_TTL ){
ShowWarning( "inter: wis data id=%d time out : from %s to %s\n", wd->id, wd->src, wd->dst );
it = wis_db.erase( it );
}else{
it++;
}
} while(wis_delnum >= WISDELLIST_MAX);
return 0;
}
}
//--------------------------------------------------------
@@ -1193,7 +1178,6 @@ int mapif_wis_reply( int mapserver_fd, char* target, uint8 flag ){
// Wisp/page request to send
int mapif_parse_WisRequest(int fd)
{
struct WisData* wd;
char name[NAME_LENGTH];
char esc_name[NAME_LENGTH*2+1];// escaped name
char* data;
@@ -1203,7 +1187,7 @@ int mapif_parse_WisRequest(int fd)
if ( fd <= 0 ) {return 0;} // check if we have a valid fd
if (RFIFOW(fd,2)-headersize >= sizeof(wd->msg)) {
if( RFIFOW( fd, 2 ) - headersize >= WHISPER_MESSAGE_SIZE ){
ShowWarning("inter: Wis message size too long.\n");
return 0;
} else if (RFIFOW(fd,2)-headersize <= 0) { // normaly, impossible, but who knows...
@@ -1237,11 +1221,11 @@ int mapif_parse_WisRequest(int fd)
{
static int wisid = 0;
CREATE(wd, struct WisData, 1);
// Whether the failure of previous wisp/page transmission (timeout)
check_ttl_wisdata();
std::shared_ptr<struct WisData> wd = std::make_shared<struct WisData>();
wd->id = ++wisid;
wd->fd = fd;
wd->len= RFIFOW(fd,2)-headersize;
@@ -1250,8 +1234,10 @@ int mapif_parse_WisRequest(int fd)
safestrncpy(wd->dst, RFIFOCP(fd,8+NAME_LENGTH), NAME_LENGTH);
safestrncpy(wd->msg, RFIFOCP(fd,8+2*NAME_LENGTH), wd->len);
wd->tick = gettick();
idb_put(wis_db, wd->id, wd);
mapif_wis_message(wd);
wis_db[wd->id] = wd;
mapif_wis_message( wd );
}
}
@@ -1263,19 +1249,20 @@ int mapif_parse_WisRequest(int fd)
// Wisp/page transmission result
int mapif_parse_WisReply(int fd)
{
int id;
int32 id;
uint8 flag;
struct WisData *wd;
id = RFIFOL(fd,2);
flag = RFIFOB(fd,6);
wd = (struct WisData*)idb_get(wis_db, id);
if (wd == NULL)
std::shared_ptr<struct WisData> wd = util::umap_find( wis_db, id );
if( wd == nullptr ){
return 0; // This wisp was probably suppress before, because it was timeout of because of target was found on another map-server
}
if ((--wd->count) <= 0 || flag != 1) {
mapif_wis_reply(wd->fd, wd->src, flag); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
idb_remove(wis_db, id);
wis_db.erase( id );
}
return 0;

View File

@@ -18,6 +18,8 @@
#include "showmsg.hpp"
#include "timer.hpp"
using namespace rathena::server_core;
//map confs
const char* MAP_CONF_NAME;
const char* INTER_CONF_NAME;
@@ -110,14 +112,12 @@ int cli_get_options(int argc, char ** argv) {
MSG_CONF_NAME_EN = argv[++i];
}
else if (strcmp(arg, "run-once") == 0) { // close the map-server as soon as its done.. for testing [Celest]
runflag = CORE_ST_STOP;
}
else if (SERVER_TYPE & (ATHENA_SERVER_LOGIN | ATHENA_SERVER_CHAR)) { //login or char
global_core->set_run_once( true );
}else if( global_core->get_type() == e_core_type::LOGIN || global_core->get_type() == e_core_type::CHARACTER ){
if (strcmp(arg, "lan-config") == 0) {
if (opt_has_next_value(arg, i, argc))
LAN_CONF_NAME = argv[++i];
}
else if (SERVER_TYPE == ATHENA_SERVER_LOGIN) { //login
}else if( global_core->get_type() == e_core_type::LOGIN ){
if (strcmp(arg, "login-config") == 0) {
if (opt_has_next_value(arg, i, argc))
LOGIN_CONF_NAME = argv[++i];
@@ -126,8 +126,7 @@ int cli_get_options(int argc, char ** argv) {
ShowError("Unknown option '%s'.\n", argv[i]);
exit(EXIT_FAILURE);
}
}
else if (SERVER_TYPE == ATHENA_SERVER_CHAR) { //char
}else if( global_core->get_type() == e_core_type::CHARACTER ){
if (strcmp(arg, "char-config") == 0) {
if (opt_has_next_value(arg, i, argc))
CHAR_CONF_NAME = argv[++i];
@@ -141,8 +140,7 @@ int cli_get_options(int argc, char ** argv) {
exit(EXIT_FAILURE);
}
}
}
else if (SERVER_TYPE == ATHENA_SERVER_MAP) { //map
}else if( global_core->get_type() == e_core_type::MAP ){
if (strcmp(arg, "map-config") == 0) {
if (opt_has_next_value(arg, i, argc))
MAP_CONF_NAME = argv[++i];

View File

@@ -128,6 +128,7 @@
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalIncludeDirectories>$(SolutionDir)3rdparty\zlib\include\;$(SolutionDir)3rdparty\mysql\include\;$(SolutionDir)3rdparty\libconfig\;$(SolutionDir)3rdparty\yaml-cpp\include\</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)3rdparty\zlib\include\;$(SolutionDir)3rdparty\libconfig\</AdditionalIncludeDirectories>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>

View File

@@ -160,6 +160,7 @@
<PreprocessorDefinitions>$(DefineConstants);WIN32;FD_SETSIZE=4096;PCRE_SUPPORT;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_WINSOCK_DEPRECATED_NO_WARNINGS;LIBCONFIG_STATIC;YY_USE_CONST;_DEBUG;_LIB;_ITERATOR_DEBUG_LEVEL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalIncludeDirectories>$(SolutionDir)\3rdparty\rapidyaml\src;$(SolutionDir)\3rdparty\rapidyaml\ext\c4core\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -235,4 +236,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@@ -37,19 +37,18 @@
#endif
#endif
/// Called when a terminate signal is received.
void (*shutdown_callback)(void) = NULL;
using namespace rathena::server_core;
Core* global_core = nullptr;
#if defined(BUILDBOT)
int buildbotflag = 0;
#endif
int runflag = CORE_ST_RUN;
char db_path[12] = "db"; /// relative path for db from server
char conf_path[12] = "conf"; /// relative path for conf from server
char *SERVER_NAME = NULL;
char SERVER_TYPE = ATHENA_SERVER_NONE;
#ifndef MINICORE // minimalist Core
// Added by Gabuzomeu
@@ -91,10 +90,9 @@ static BOOL WINAPI console_handler(DWORD c_event) {
case CTRL_CLOSE_EVENT:
case CTRL_LOGOFF_EVENT:
case CTRL_SHUTDOWN_EVENT:
if( shutdown_callback != NULL )
shutdown_callback();
else
runflag = CORE_ST_STOP;// auto-shutdown
if( global_core != nullptr ){
global_core->signal_shutdown();
}
break;
default:
return FALSE;
@@ -119,14 +117,15 @@ static void sig_proc(int sn) {
case SIGTERM:
if (++is_called > 3)
exit(EXIT_SUCCESS);
if( shutdown_callback != NULL )
shutdown_callback();
else
runflag = CORE_ST_STOP;// auto-shutdown
if( global_core != nullptr ){
global_core->signal_shutdown();
}
break;
case SIGSEGV:
case SIGFPE:
do_abort();
if( global_core != nullptr ){
global_core->signal_crash();
}
// Pass the signal to the system's default handler
compat_signal(sn, SIG_DFL);
raise(sn);
@@ -329,11 +328,14 @@ void usercheck(void)
#endif
}
/*======================================
* CORE : MAINROUTINE
*--------------------------------------*/
int main (int argc, char **argv)
{
int Core::start( int argc, char **argv ){
if( this->get_status() != e_core_status::NOT_STARTED) {
ShowFatalError( "Core was already started and cannot be started again!\n" );
return EXIT_FAILURE;
}
this->set_status( e_core_status::CORE_INITIALIZING );
{// initialize program arguments
char *p1;
if((p1 = strrchr(argv[0], '/')) != NULL || (p1 = strrchr(argv[0], '\\')) != NULL ){
@@ -352,17 +354,10 @@ int main (int argc, char **argv)
}
malloc_init();// needed for Show* in display_title() [FlavioJS]
#ifdef MINICORE // minimalist Core
display_title();
usercheck();
do_init(argc,argv);
do_final();
#else// not MINICORE
set_server_type();
display_title();
usercheck();
#ifndef MINICORE
Sql_Init();
db_init();
signals_init();
@@ -370,24 +365,41 @@ int main (int argc, char **argv)
#ifdef _WIN32
cevents_init();
#endif
timer_init();
socket_init();
#endif
do_init(argc,argv);
this->set_status( e_core_status::CORE_INITIALIZED );
// Main runtime cycle
while (runflag != CORE_ST_STOP) {
t_tick next = do_timer(gettick_nocache());
if (SERVER_TYPE != ATHENA_SERVER_WEB)
do_sockets(next);
else
do_wait(next);
this->set_status( e_core_status::SERVER_INITIALIZING );
if( !this->initialize( argc, argv ) ){
return EXIT_FAILURE;
}
do_final();
// If initialization did not trigger shutdown
if( this->m_status != e_core_status::STOPPING ){
this->set_status( e_core_status::SERVER_INITIALIZED );
this->set_status( e_core_status::RUNNING );
#ifndef MINICORE
if( !this->m_run_once ){
// Main runtime cycle
while( this->get_status() == e_core_status::RUNNING ){
t_tick next = do_timer( gettick_nocache() );
this->handle_main( next );
}
}
#endif
this->set_status( e_core_status::STOPPING );
}
this->set_status( e_core_status::SERVER_FINALIZING );
this->finalize();
this->set_status( e_core_status::SERVER_FINALIZED );
this->set_status( e_core_status::CORE_FINALIZING );
#ifndef MINICORE
timer_final();
socket_final();
db_final();
@@ -395,6 +407,7 @@ int main (int argc, char **argv)
#endif
malloc_final();
this->set_status( e_core_status::CORE_FINALIZED );
#if defined(BUILDBOT)
if( buildbotflag ){
@@ -402,5 +415,71 @@ int main (int argc, char **argv)
}
#endif
return 0;
this->set_status( e_core_status::STOPPED );
return EXIT_SUCCESS;
}
bool Core::initialize( int argc, char* argv[] ){
// Do nothing
return true;
}
void Core::handle_main( t_tick next ){
#ifndef MINICORE
// By default we handle all socket packets
do_sockets( next );
#endif
}
void Core::handle_crash(){
// Do nothing
}
void Core::handle_shutdown(){
// Do nothing
}
void Core::finalize(){
// Do nothing
}
void Core::set_status( e_core_status status ){
this->m_status = status;
}
e_core_status Core::get_status(){
return this->m_status;
}
e_core_type Core::get_type(){
return this->m_type;
}
bool Core::is_running(){
return this->get_status() == e_core_status::RUNNING;
}
void Core::set_run_once( bool run_once ){
this->m_run_once = run_once;
}
void Core::signal_crash(){
this->set_status( e_core_status::STOPPING );
if( this->m_crashed ){
ShowFatalError( "Received another crash signal, while trying to handle the last crash!\n" );
}else{
ShowFatalError( "Received a crash signal, trying to handle it as good as possible!\n" );
this->m_crashed = true;
this->handle_crash();
}
// Now stop the process
exit( EXIT_FAILURE );
}
void Core::signal_shutdown(){
this->set_status( e_core_status::STOPPING );
this->handle_shutdown();
}

View File

@@ -4,55 +4,102 @@
#ifndef CORE_HPP
#define CORE_HPP
#include <string>
#include <vector>
#include "timer.hpp"
#ifdef _WIN32
#include "winapi.hpp" // Console close event handling
#endif
/* so that developers with --enable-debug can raise signals from any section of the code they'd like */
#ifdef DEBUG
#include <signal.h>
#endif
extern int arg_c;
extern char **arg_v;
#if defined(BUILDBOT)
extern int buildbotflag;
#endif
#define UNKNOWN_VERSION '\x02'
/// @see E_CORE_ST
extern int runflag;
extern char *SERVER_NAME;
extern char db_path[12]; /// relative path for db from servers
extern char conf_path[12]; /// relative path for conf from servers
enum {
ATHENA_SERVER_NONE = 0, // not defined
ATHENA_SERVER_LOGIN = 1, // login server
ATHENA_SERVER_CHAR = 2, // char server
ATHENA_SERVER_INTER = 4, // inter server
ATHENA_SERVER_MAP = 8, // map server
ATHENA_SERVER_WEB = 16, // web server
};
extern char SERVER_TYPE;
extern int parse_console(const char* buf);
const char *get_svn_revision(void);
const char *get_git_hash(void);
extern int do_init(int,char**);
extern void set_server_type(void);
extern void do_abort(void);
extern void do_final(void);
/// The main loop continues until runflag is CORE_ST_STOP
enum E_CORE_ST
{
CORE_ST_STOP = 0,
CORE_ST_RUN,
CORE_ST_LAST
};
namespace rathena{
namespace server_core{
enum class e_core_status{
NOT_STARTED,
CORE_INITIALIZING,
CORE_INITIALIZED,
SERVER_INITIALIZING,
SERVER_INITIALIZED,
RUNNING,
STOPPING,
SERVER_FINALIZING,
SERVER_FINALIZED,
CORE_FINALIZING,
CORE_FINALIZED,
STOPPED,
};
/// Called when a terminate signal is received. (Ctrl+C pressed)
/// If NULL, runflag is set to CORE_ST_STOP instead.
extern void (*shutdown_callback)(void);
enum class e_core_type{
LOGIN,
CHARACTER,
MAP,
TOOL,
WEB
};
class Core{
private:
e_core_status m_status;
e_core_type m_type;
bool m_run_once;
bool m_crashed;
protected:
virtual bool initialize( int argc, char* argv[] );
virtual void handle_main( t_tick next );
virtual void finalize();
virtual void handle_crash();
virtual void handle_shutdown();
void set_status( e_core_status status );
public:
Core( e_core_type type ){
this->m_status = e_core_status::NOT_STARTED;
this->m_run_once = false;
this->m_crashed = false;
this->m_type = type;
}
e_core_status get_status();
e_core_type get_type();
bool is_running();
// TODO: refactor to protected
void set_run_once( bool run_once );
void signal_crash();
void signal_shutdown();
int start( int argc, char* argv[] );
};
}
}
extern rathena::server_core::Core* global_core;
template <typename T> int main_core( int argc, char *argv[] ){
T server = {};
global_core = &server;
return server.start( argc, argv );
}
#endif /* CORE_HPP */

View File

@@ -193,7 +193,7 @@ static void *ers_obj_alloc_entry(ERS *self)
instance->Cache->ReuseList = instance->Cache->ReuseList->Next;
} else if (instance->Cache->Free > 0) {
instance->Cache->Free--;
ret = &instance->Cache->Blocks[instance->Cache->Used - 1][instance->Cache->Free * instance->Cache->ObjectSize + sizeof(struct ers_list)];
ret = &instance->Cache->Blocks[instance->Cache->Used - 1][static_cast<size_t>( instance->Cache->Free ) * static_cast<size_t>( instance->Cache->ObjectSize ) + sizeof( struct ers_list )];
} else {
if (instance->Cache->Used == instance->Cache->Max) {
instance->Cache->Max = (instance->Cache->Max * 4) + 3;
@@ -204,7 +204,7 @@ static void *ers_obj_alloc_entry(ERS *self)
instance->Cache->Used++;
instance->Cache->Free = instance->Cache->ChunkSize -1;
ret = &instance->Cache->Blocks[instance->Cache->Used - 1][instance->Cache->Free * instance->Cache->ObjectSize + sizeof(struct ers_list)];
ret = &instance->Cache->Blocks[instance->Cache->Used - 1][static_cast<size_t>( instance->Cache->Free ) * static_cast<size_t>( instance->Cache->ObjectSize ) + sizeof( struct ers_list )];
}
instance->Count++;

View File

@@ -81,6 +81,12 @@ typedef uint32 t_itemid;
#define MAX_AMOUNT 30000 ////Max amount of a single stacked item
#define MAX_ZENY INT_MAX ///Max zeny
#define MAX_BANK_ZENY SINT32_MAX ///Max zeny in Bank
#ifndef MAX_CASHPOINT
#define MAX_CASHPOINT INT_MAX
#endif
#ifndef MAX_KAFRAPOINT
#define MAX_KAFRAPOINT INT_MAX
#endif
#define MAX_FAME 1000000000 ///Max fame points
#define MAX_CART 100 ///Maximum item in cart
#define MAX_SKILL 1454 ///Maximum skill can be hold by Player, Homunculus, & Mercenary (skill list) AND skill_db limit
@@ -353,8 +359,8 @@ enum equip_pos : uint32 {
};
struct point {
unsigned short map;
short x,y;
uint16 map;
uint16 x,y;
};
struct startitem {
@@ -402,6 +408,8 @@ struct status_change_data {
unsigned short type; //SC_type
long val1, val2, val3, val4;
t_tick tick; //Remaining duration.
t_tick tick_total; // Total duration
t_tick tick_time; // Interval duration
};
#define MAX_BONUS_SCRIPT_LENGTH 512
@@ -693,14 +701,14 @@ struct party {
struct party_member member[MAX_PARTY];
};
struct map_session_data;
class map_session_data;
struct guild_member {
uint32 account_id, char_id;
short hair,hair_color,gender,class_,lv;
t_exp exp;
short online,position;
char name[NAME_LENGTH];
struct map_session_data *sd;
map_session_data *sd;
unsigned char modified;
uint32 last_login;
};
@@ -754,11 +762,25 @@ struct guild {
int32 chargeshout_flag_id;
};
enum e_woe_type{
WOE_FIRST_EDITION = 1,
WOE_SECOND_EDITION,
WOE_THIRD_EDITION,
WOE_MAX
};
struct guild_castle {
int castle_id;
int mapindex;
char castle_name[NAME_LENGTH];
char castle_event[NPC_NAME_LENGTH];
e_woe_type type;
uint16 client_id;
bool warp_enabled;
uint16 warp_x;
uint16 warp_y;
uint32 zeny;
uint32 zeny_siege;
int guild_id;
int economy;
int defense;
@@ -1121,7 +1143,7 @@ struct clan{
char master[NAME_LENGTH];
char map[MAP_NAME_LENGTH_EXT];
short max_member, connect_member;
struct map_session_data *members[MAX_CLAN];
map_session_data *members[MAX_CLAN];
struct clan_alliance alliance[MAX_CLANALLIANCE];
unsigned short instance_id;
};

View File

@@ -40,9 +40,6 @@
#endif
#endif
#include <chrono>
#include <thread>
#include "cbasetypes.hpp"
#include "malloc.hpp"
#include "mmo.hpp"
@@ -890,14 +887,6 @@ int WFIFOSET(int fd, size_t len)
return 0;
}
// replacement for do_sockets, where it does nothing
int do_wait(t_tick next)
{
std::this_thread::sleep_for(std::chrono::milliseconds(next));
return 0;
}
int do_sockets(t_tick next)
{
#ifndef SOCKET_EPOLL

View File

@@ -133,7 +133,6 @@ int WFIFOSET(int fd, size_t len);
int RFIFOSKIP(int fd, size_t len);
int do_sockets(t_tick next);
int do_wait(t_tick next);
void do_close(int fd);
void socket_init(void);
void socket_final(void);

View File

@@ -109,6 +109,7 @@
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>FD_SETSIZE=4096;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_WINSOCK_DEPRECATED_NO_WARNINGS;LIBCONFIG_STATIC;YY_USE_CONST;WIN32;_DEBUG;_CONSOLE;_LIB;_ITERATOR_DEBUG_LEVEL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>

Some files were not shown because too many files have changed in this diff Show More