Adapted the scheme buffer for Classic.
This commit is contained in:
5
L2J_Mobius_Classic_2.0_Saviors/dist/db_installer/sql/game/buffer_schemes.sql
vendored
Normal file
5
L2J_Mobius_Classic_2.0_Saviors/dist/db_installer/sql/game/buffer_schemes.sql
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
CREATE TABLE IF NOT EXISTS `buffer_schemes` (
|
||||
`object_id` INT UNSIGNED NOT NULL DEFAULT '0',
|
||||
`scheme_name` VARCHAR(16) NOT NULL DEFAULT 'default',
|
||||
`skills` VARCHAR(200) NOT NULL
|
||||
);
|
10
L2J_Mobius_Classic_2.0_Saviors/dist/game/config/Custom/ShemeBuffer.ini
vendored
Normal file
10
L2J_Mobius_Classic_2.0_Saviors/dist/game/config/Custom/ShemeBuffer.ini
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
#=============================================================
|
||||
# Buffer
|
||||
#=============================================================
|
||||
# Also check data\SchemeBufferSkills.xml
|
||||
|
||||
# Maximum number of available schemes per player.
|
||||
BufferMaxSchemesPerChar = 4
|
||||
|
||||
# Static cost of buffs ; override skills price if different of -1.
|
||||
BufferStaticCostPerBuff = -1
|
69
L2J_Mobius_Classic_2.0_Saviors/dist/game/data/SchemeBufferSkills.xml
vendored
Normal file
69
L2J_Mobius_Classic_2.0_Saviors/dist/game/data/SchemeBufferSkills.xml
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<list xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="xsd/SchemeBufferSkills.xsd">
|
||||
<category type="Buffs">
|
||||
<buff id="1035" price="0" desc="Increases resistance to mental attacks." /> <!-- Mental Shield -->
|
||||
<buff id="1036" price="0" desc="Increases M. Def." /> <!-- Magic Barrier -->
|
||||
<buff id="1040" price="0" desc="Increases P. Def." /> <!-- Shield -->
|
||||
<buff id="1045" price="0" desc="Increases maximum HP." /> <!-- Blessed Body -->
|
||||
<buff id="1048" price="0" desc="Increases maximum MP." /> <!-- Blessed Soul -->
|
||||
<buff id="1059" price="0" desc="Increases M. Atk." /> <!-- Empower -->
|
||||
<buff id="1062" price="0" desc="Reduces def. and increase atk. power." /> <!-- Berserker Spirit -->
|
||||
<buff id="1068" price="0" desc="Increases P. Atk." /> <!-- Might -->
|
||||
<buff id="1077" price="0" desc="Increases critical attack rate." /> <!-- Focus -->
|
||||
<buff id="1078" price="0" desc="Increases magic concentration." /> <!-- Concentration -->
|
||||
<buff id="1085" price="0" desc="Increases Casting Spd." /> <!-- Acumen -->
|
||||
<buff id="1086" price="0" desc="Increases Atk. Spd." /> <!-- Haste -->
|
||||
<buff id="1087" price="0" desc="Increases Evasion." /> <!-- Agility -->
|
||||
<buff id="1204" price="0" desc="Increases Speed." /> <!-- Wind Walk -->
|
||||
<buff id="1240" price="0" desc="Increases Accuracy." /> <!-- Guidance -->
|
||||
<buff id="1242" price="0" desc="Increases critical attack." /> <!-- Death Whisper -->
|
||||
<buff id="1243" price="0" desc="Increases shield defense rate." /> <!-- Bless Shield -->
|
||||
<buff id="1259" price="0" desc="Increases resistance to stun attack." /> <!-- Resist Shock -->
|
||||
<buff id="1268" price="0" desc="Restores HP using inflicted damage." /> <!-- Vampiric Rage -->
|
||||
<buff id="1303" price="0" desc="Increases crit. rate of magic attacks." /> <!-- Wild Magic -->
|
||||
<buff id="1304" price="0" desc="Increases shield defense power." /> <!-- Advanced Block -->
|
||||
<buff id="1352" price="0" desc="Increases resistance to atures." /> <!-- Elemental Protection -->
|
||||
<buff id="1353" price="0" desc="Increases resistance to dark attack." /> <!-- Divine Protection -->
|
||||
<buff id="1354" price="0" desc="Increases resistance to de-buff attack." /> <!-- Arcane Protection -->
|
||||
<buff id="1355" price="0" desc="Increases mage abilities." /> <!-- Prophecy of Water -->
|
||||
<buff id="1356" price="0" desc="Increases fighter abilities." /> <!-- Prophecy of Fire -->
|
||||
<buff id="1357" price="0" desc="Increases dagger abilities." /> <!-- Prophecy of Wind -->
|
||||
<buff id="1363" price="0" desc="Increases combat abilities." /> <!-- Chant of Victory -->
|
||||
<buff id="1388" price="0" desc="Increases P. Atk." /> <!-- Greater Might -->
|
||||
<buff id="1389" price="0" desc="Increases P. Def." /> <!-- Greater Shield -->
|
||||
<buff id="1390" price="0" desc="Increases P. Atk." /> <!-- War Chant -->
|
||||
<buff id="1391" price="0" desc="Increases P. Def." /> <!-- Earth Chant -->
|
||||
<buff id="1397" price="0" desc="Decreases MP consumption rate." /> <!-- Clarity -->
|
||||
<buff id="1413" price="0" desc="Increases mage abilities." /> <!-- Magnus' Chant -->
|
||||
</category>
|
||||
<category type="Dances">
|
||||
<buff id="271" price="0" desc="Increases P. Atk." /> <!-- Dance of the Warrior -->
|
||||
<buff id="272" price="0" desc="Increases Accuracy." /> <!-- Dance of Inspiration -->
|
||||
<buff id="273" price="0" desc="Increases M. Atk." /> <!-- Dance of the Mystic -->
|
||||
<buff id="274" price="0" desc="Increases critical damage." /> <!-- Dance of Fire -->
|
||||
<buff id="275" price="0" desc="Increases attack speed." /> <!-- Dance of Fury -->
|
||||
<buff id="276" price="0" desc="Increases Casting Spd." /> <!-- Dance of Concentration -->
|
||||
<buff id="277" price="0" desc="Sacred power to physical attack." /> <!-- Dance of Light -->
|
||||
<buff id="307" price="0" desc="Increases water resistance." /> <!-- Dance of Aqua Guard -->
|
||||
<buff id="309" price="0" desc="Increases earth resistance." /> <!-- Dance of Earth Guard -->
|
||||
<buff id="310" price="0" desc="Restores HP by inflicted damage." /> <!-- Dance of the Vampire -->
|
||||
<buff id="311" price="0" desc="Increases resistance to terrain damage." /> <!-- Dance of Protection -->
|
||||
<buff id="365" price="0" desc="Increases rate of magic crit. damage." /> <!-- Siren's Dance -->
|
||||
</category>
|
||||
<category type="Songs">
|
||||
<buff id="264" price="0" desc="Increases P. Def." /> <!-- Song of Earth -->
|
||||
<buff id="265" price="0" desc="Increases HP regeneration." /> <!-- Song of Life -->
|
||||
<buff id="266" price="0" desc="Increases Evasion." /> <!-- Song of Water -->
|
||||
<buff id="267" price="0" desc="Increases M. Def." /> <!-- Song of Warding -->
|
||||
<buff id="268" price="0" desc="Increases movement." /> <!-- Song of Wind -->
|
||||
<buff id="269" price="0" desc="Increases critical rate." /> <!-- Song of Hunter -->
|
||||
<buff id="270" price="0" desc="Increases resistance to dark magic." /> <!-- Song of Invocation -->
|
||||
<buff id="304" price="0" desc="Increases maximum HP." /> <!-- Song of Vitality -->
|
||||
<buff id="305" price="0" desc="Reflects damage received." /> <!-- Song of Vengeance -->
|
||||
<buff id="306" price="0" desc="Increases resistance to fire." /> <!-- Song of Flame Guard -->
|
||||
<buff id="308" price="0" desc="Increases resistance to wind." /> <!-- Song of Storm Guard -->
|
||||
<buff id="349" price="0" desc="Decreases re-use time." /> <!-- Song of Renewal -->
|
||||
<buff id="363" price="0" desc="Increases MP regeneration rate." /> <!-- Song of Meditation -->
|
||||
<buff id="364" price="0" desc="Decreases re-use time of physical skills." /> <!-- Song of Champion -->
|
||||
</category>
|
||||
</list>
|
14
L2J_Mobius_Classic_2.0_Saviors/dist/game/data/html/mods/SchemeBuffer/50008-1.htm
vendored
Normal file
14
L2J_Mobius_Classic_2.0_Saviors/dist/game/data/html/mods/SchemeBuffer/50008-1.htm
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<html><body>
|
||||
<font color="LEVEL">You can create up to %max_schemes% schemes.</font> Is it clear for you?<br1>
|
||||
If not, read until you get it! I can't afford idiots...<br>
|
||||
You can register a new scheme filling this form, here!
|
||||
<center><table width=220>
|
||||
<tr>
|
||||
<td width="140"><edit var="name" width=140 height=15></td>
|
||||
<td width="60"><button value="Create" action="bypass -h npc_%objectId%_createscheme $name" width=75 height=21 back="L2UI_ch3.Btn1_normalOn" fore="L2UI_ch3.Btn1_normal"></td>
|
||||
</tr>
|
||||
</table></center><br>
|
||||
Here are listed your schemes and their fee.<br>
|
||||
%schemes%<br>
|
||||
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h npc_%objectId%_menu">Back</Button>
|
||||
</body></html>
|
8
L2J_Mobius_Classic_2.0_Saviors/dist/game/data/html/mods/SchemeBuffer/50008-2.htm
vendored
Normal file
8
L2J_Mobius_Classic_2.0_Saviors/dist/game/data/html/mods/SchemeBuffer/50008-2.htm
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
<html><body>
|
||||
<font color="LEVEL">%schemename%</font> scheme holds %count% buffs.<br>
|
||||
<center>
|
||||
%typesframe%<br>
|
||||
%skilllistframe%<br>
|
||||
</center>
|
||||
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h npc_%objectId%_support">Back</Button>
|
||||
</body></html>
|
8
L2J_Mobius_Classic_2.0_Saviors/dist/game/data/html/mods/SchemeBuffer/50008.htm
vendored
Normal file
8
L2J_Mobius_Classic_2.0_Saviors/dist/game/data/html/mods/SchemeBuffer/50008.htm
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
<html><body>
|
||||
Hello stranger!<br>
|
||||
Yup, you're right, I decided to share some of my powerful buffs in order to improve your pew-pew-bum-zap abilities.<br>
|
||||
What can I do for you?<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_support">Magic support</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_heal">Heal me and my pet</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_cleanup">Cleanup all effects on me and my pet</Button>
|
||||
</body></html>
|
21
L2J_Mobius_Classic_2.0_Saviors/dist/game/data/stats/npcs/custom/SchemeBuffer.xml
vendored
Normal file
21
L2J_Mobius_Classic_2.0_Saviors/dist/game/data/stats/npcs/custom/SchemeBuffer.xml
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<list xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../xsd/npcs.xsd">
|
||||
<npc id="50008" displayId="9000" type="L2SchemeBuffer" name="Rosalia" usingServerSideName="true" title="Scheme Buffer" usingServerSideTitle="true">
|
||||
<race>HUMAN</race>
|
||||
<sex>FEMALE</sex>
|
||||
<stats>
|
||||
<vitals hp="2444.46819" hpRegen="7.5" mp="1345.8" mpRegen="2.7" />
|
||||
<attack physical="688.86373" magical="470.40463" random="30" critical="4" accuracy="95" attackSpeed="253" type="SWORD" range="40" distance="80" width="120" />
|
||||
<defence physical="295.91597" magical="216.53847" />
|
||||
<speed>
|
||||
<walk ground="50" />
|
||||
<run ground="120" />
|
||||
</speed>
|
||||
</stats>
|
||||
<status attackable="false" />
|
||||
<collision>
|
||||
<radius normal="11" />
|
||||
<height normal="22.25" />
|
||||
</collision>
|
||||
</npc>
|
||||
</list>
|
32
L2J_Mobius_Classic_2.0_Saviors/dist/game/data/xsd/SchemeBufferSkills.xsd
vendored
Normal file
32
L2J_Mobius_Classic_2.0_Saviors/dist/game/data/xsd/SchemeBufferSkills.xsd
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:element name="list">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="category" maxOccurs="unbounded" minOccurs="0">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Magnus' Chant Siren's Dance Song of Champion</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="buff" maxOccurs="unbounded" minOccurs="0">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Mental Shield Magic Barrier Shield Blessed Body Blessed Soul Empower Berserker Spirit Might Focus Concentration Acumen Haste Agility Wind Walk Guidance Death Whisper Bless Shield Resist Shock Vampiric Rage Wild Magic Advanced Block Elemental Protection Divine Protection Arcane Protection Prophecy of Water Prophecy of Fire Prophecy of Wind Chant of Victory Greater Might Greater Shield War Chant Earth Chant Clarity Dance of the Warrior Dance of Inspiration Dance of the Mystic Dance of Fire Dance of Fury Dance of Concentration Dance of Light Dance of Aqua Guard Dance of Earth Guard Dance of the Vampire Dance of Protection Song of Earth Song of Life Song of Water Song of Warding Song of Wind Song of Hunter Song of Invocation Song of Vitality Song of Vengeance Song of Flame Guard Song of Storm Guard Song of Renewal Song of Meditation</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:complexType>
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="xs:string">
|
||||
<xs:attribute type="xs:short" name="id" use="optional"/>
|
||||
<xs:attribute type="xs:byte" name="price" use="optional"/>
|
||||
<xs:attribute type="xs:string" name="desc" use="optional"/>
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute type="xs:string" name="type" use="optional"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
@@ -133,6 +133,7 @@ public final class Config
|
||||
public static final String CUSTOM_SCREEN_WELCOME_MESSAGE_CONFIG_FILE = "./config/Custom/ScreenWelcomeMessage.ini";
|
||||
public static final String CUSTOM_SELL_BUFFS_CONFIG_FILE = "./config/Custom/SellBuffs.ini";
|
||||
public static final String CUSTOM_SERVER_TIME_CONFIG_FILE = "./config/Custom/ServerTime.ini";
|
||||
public static final String CUSTOM_SCHEME_BUFFER_CONFIG_FILE = "./config/Custom/ShemeBuffer.ini";
|
||||
public static final String CUSTOM_STARTING_LOCATION_CONFIG_FILE = "./config/Custom/StartingLocation.ini";
|
||||
public static final String CUSTOM_VOTE_REWARD_CONFIG_FILE = "./config/Custom/VoteReward.ini";
|
||||
public static final String CUSTOM_WALKER_BOT_PROTECTION_CONFIG_FILE = "./config/Custom/WalkerBotProtection.ini";
|
||||
@@ -1008,6 +1009,8 @@ public final class Config
|
||||
public static boolean OFFLINE_FAME;
|
||||
public static boolean STORE_OFFLINE_TRADE_IN_REALTIME;
|
||||
public static boolean DISPLAY_SERVER_TIME;
|
||||
public static int BUFFER_MAX_SCHEMES;
|
||||
public static int BUFFER_STATIC_BUFF_COST;
|
||||
public static boolean WELCOME_MESSAGE_ENABLED;
|
||||
public static String WELCOME_MESSAGE_TEXT;
|
||||
public static int WELCOME_MESSAGE_TIME;
|
||||
@@ -2769,6 +2772,12 @@ public final class Config
|
||||
|
||||
DISPLAY_SERVER_TIME = ServerTime.getBoolean("DisplayServerTime", false);
|
||||
|
||||
// Load SchemeBuffer config file (if exists)
|
||||
final PropertiesParser SchemeBuffer = new PropertiesParser(CUSTOM_SCHEME_BUFFER_CONFIG_FILE);
|
||||
|
||||
BUFFER_MAX_SCHEMES = SchemeBuffer.getInt("BufferMaxSchemesPerChar", 4);
|
||||
BUFFER_STATIC_BUFF_COST = SchemeBuffer.getInt("BufferStaticCostPerBuff", -1);
|
||||
|
||||
// Load StartingLocation config file (if exists)
|
||||
final PropertiesParser StartingLocation = new PropertiesParser(CUSTOM_STARTING_LOCATION_CONFIG_FILE);
|
||||
|
||||
|
@@ -97,6 +97,7 @@ import com.l2jmobius.gameserver.data.xml.impl.VariationData;
|
||||
import com.l2jmobius.gameserver.datatables.BotReportTable;
|
||||
import com.l2jmobius.gameserver.datatables.EventDroplist;
|
||||
import com.l2jmobius.gameserver.datatables.ItemTable;
|
||||
import com.l2jmobius.gameserver.datatables.SchemeBufferTable;
|
||||
import com.l2jmobius.gameserver.geoengine.GeoEngine;
|
||||
import com.l2jmobius.gameserver.handler.ConditionHandler;
|
||||
import com.l2jmobius.gameserver.handler.DailyMissionHandler;
|
||||
@@ -317,6 +318,7 @@ public class GameServer
|
||||
StaticObjectData.getInstance();
|
||||
ItemAuctionManager.getInstance();
|
||||
CastleManager.getInstance().loadInstances();
|
||||
SchemeBufferTable.getInstance();
|
||||
GrandBossManager.getInstance();
|
||||
EventDroplist.getInstance();
|
||||
CommissionManager.getInstance();
|
||||
|
@@ -26,6 +26,7 @@ import com.l2jmobius.commons.database.DatabaseFactory;
|
||||
import com.l2jmobius.gameserver.data.sql.impl.ClanTable;
|
||||
import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable;
|
||||
import com.l2jmobius.gameserver.datatables.BotReportTable;
|
||||
import com.l2jmobius.gameserver.datatables.SchemeBufferTable;
|
||||
import com.l2jmobius.gameserver.instancemanager.CastleManorManager;
|
||||
import com.l2jmobius.gameserver.instancemanager.CeremonyOfChaosManager;
|
||||
import com.l2jmobius.gameserver.instancemanager.CursedWeaponsManager;
|
||||
@@ -521,6 +522,10 @@ public class Shutdown extends Thread
|
||||
GlobalVariablesManager.getInstance().storeMe();
|
||||
LOGGER.info("Global Variables Manager: Variables saved(" + tc.getEstimatedTimeAndRestartCounter() + "ms).");
|
||||
|
||||
// Schemes save.
|
||||
SchemeBufferTable.getInstance().saveSchemes();
|
||||
LOGGER.info("SchemeBufferTable data has been saved.");
|
||||
|
||||
// Save items on ground before closing
|
||||
if (Config.SAVE_DROPPED_ITEM)
|
||||
{
|
||||
|
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
package com.l2jmobius.gameserver.datatables;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import com.l2jmobius.Config;
|
||||
import com.l2jmobius.commons.database.DatabaseFactory;
|
||||
import com.l2jmobius.gameserver.model.holders.BuffSkillHolder;
|
||||
|
||||
/**
|
||||
* This class loads available skills and stores players' buff schemes into _schemesTable.
|
||||
*/
|
||||
public class SchemeBufferTable
|
||||
{
|
||||
private static final Logger LOGGER = Logger.getLogger(SchemeBufferTable.class.getName());
|
||||
|
||||
private static final String LOAD_SCHEMES = "SELECT * FROM buffer_schemes";
|
||||
private static final String DELETE_SCHEMES = "TRUNCATE TABLE buffer_schemes";
|
||||
private static final String INSERT_SCHEME = "INSERT INTO buffer_schemes (object_id, scheme_name, skills) VALUES (?,?,?)";
|
||||
|
||||
private final Map<Integer, HashMap<String, ArrayList<Integer>>> _schemesTable = new ConcurrentHashMap<>();
|
||||
private final Map<Integer, BuffSkillHolder> _availableBuffs = new LinkedHashMap<>();
|
||||
|
||||
public SchemeBufferTable()
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
try (Connection con = DatabaseFactory.getInstance().getConnection())
|
||||
{
|
||||
PreparedStatement st = con.prepareStatement(LOAD_SCHEMES);
|
||||
ResultSet rs = st.executeQuery();
|
||||
|
||||
while (rs.next())
|
||||
{
|
||||
final int objectId = rs.getInt("object_id");
|
||||
|
||||
final String schemeName = rs.getString("scheme_name");
|
||||
final String[] skills = rs.getString("skills").split(",");
|
||||
|
||||
ArrayList<Integer> schemeList = new ArrayList<>();
|
||||
|
||||
for (String skill : skills)
|
||||
{
|
||||
// Don't feed the skills list if the list is empty.
|
||||
if (skill.isEmpty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
schemeList.add(Integer.valueOf(skill));
|
||||
}
|
||||
|
||||
setScheme(objectId, schemeName, schemeList);
|
||||
count++;
|
||||
}
|
||||
|
||||
rs.close();
|
||||
st.close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.warning("SchemeBufferTable: Failed to load buff schemes : " + e);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder db = dbf.newDocumentBuilder();
|
||||
Document doc = db.parse(new File("./data/SchemeBufferSkills.xml"));
|
||||
|
||||
final Node n = doc.getFirstChild();
|
||||
|
||||
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
|
||||
{
|
||||
if (!d.getNodeName().equalsIgnoreCase("category"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
final String category = d.getAttributes().getNamedItem("type").getNodeValue();
|
||||
|
||||
for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
|
||||
{
|
||||
if (!c.getNodeName().equalsIgnoreCase("buff"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
final NamedNodeMap attrs = c.getAttributes();
|
||||
final int skillId = Integer.parseInt(attrs.getNamedItem("id").getNodeValue());
|
||||
|
||||
_availableBuffs.put(skillId, new BuffSkillHolder(skillId, Integer.parseInt(attrs.getNamedItem("price").getNodeValue()), category, attrs.getNamedItem("desc").getNodeValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.warning("SchemeBufferTable: Failed to load buff info : " + e);
|
||||
}
|
||||
LOGGER.info("SchemeBufferTable: Loaded " + count + " players schemes and " + _availableBuffs.size() + " available buffs.");
|
||||
}
|
||||
|
||||
public void saveSchemes()
|
||||
{
|
||||
try (Connection con = DatabaseFactory.getInstance().getConnection())
|
||||
{
|
||||
// Delete all entries from database.
|
||||
PreparedStatement st = con.prepareStatement(DELETE_SCHEMES);
|
||||
st.execute();
|
||||
st.close();
|
||||
|
||||
st = con.prepareStatement(INSERT_SCHEME);
|
||||
|
||||
// Save _schemesTable content.
|
||||
for (Map.Entry<Integer, HashMap<String, ArrayList<Integer>>> player : _schemesTable.entrySet())
|
||||
{
|
||||
for (Map.Entry<String, ArrayList<Integer>> scheme : player.getValue().entrySet())
|
||||
{
|
||||
// Build a String composed of skill ids seperated by a ",".
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
for (int skillId : scheme.getValue())
|
||||
{
|
||||
sb.append(skillId + ",");
|
||||
}
|
||||
|
||||
// Delete the last "," : must be called only if there is something to delete !
|
||||
if (sb.length() > 0)
|
||||
{
|
||||
sb.setLength(sb.length() - 1);
|
||||
}
|
||||
|
||||
st.setInt(1, player.getKey());
|
||||
st.setString(2, scheme.getKey());
|
||||
st.setString(3, sb.toString());
|
||||
st.addBatch();
|
||||
}
|
||||
}
|
||||
st.executeBatch();
|
||||
st.close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.warning("BufferTableScheme: Error while saving schemes : " + e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setScheme(int playerId, String schemeName, ArrayList<Integer> list)
|
||||
{
|
||||
if (!_schemesTable.containsKey(playerId))
|
||||
{
|
||||
_schemesTable.put(playerId, new HashMap<String, ArrayList<Integer>>());
|
||||
}
|
||||
else if (_schemesTable.get(playerId).size() >= Config.BUFFER_MAX_SCHEMES)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_schemesTable.get(playerId).put(schemeName, list);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param playerId : The player objectId to check.
|
||||
* @return the list of schemes for a given player.
|
||||
*/
|
||||
public Map<String, ArrayList<Integer>> getPlayerSchemes(int playerId)
|
||||
{
|
||||
return _schemesTable.get(playerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param playerId : The player objectId to check.
|
||||
* @param schemeName : The scheme name to check.
|
||||
* @return the List holding skills for the given scheme name and player, or null (if scheme or player isn't registered).
|
||||
*/
|
||||
public List<Integer> getScheme(int playerId, String schemeName)
|
||||
{
|
||||
if ((_schemesTable.get(playerId) == null) || (_schemesTable.get(playerId).get(schemeName) == null))
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return _schemesTable.get(playerId).get(schemeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param playerId : The player objectId to check.
|
||||
* @param schemeName : The scheme name to check.
|
||||
* @param skillId : The skill id to check.
|
||||
* @return true if the skill is already registered on the scheme, or false otherwise.
|
||||
*/
|
||||
public boolean getSchemeContainsSkill(int playerId, String schemeName, int skillId)
|
||||
{
|
||||
final List<Integer> skills = getScheme(playerId, schemeName);
|
||||
if (skills.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int id : skills)
|
||||
{
|
||||
if (id == skillId)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param groupType : The type of skills to return.
|
||||
* @return a list of skills ids based on the given groupType.
|
||||
*/
|
||||
public List<Integer> getSkillsIdsByType(String groupType)
|
||||
{
|
||||
List<Integer> skills = new ArrayList<>();
|
||||
for (BuffSkillHolder skill : _availableBuffs.values())
|
||||
{
|
||||
if (skill.getType().equalsIgnoreCase(groupType))
|
||||
{
|
||||
skills.add(skill.getId());
|
||||
}
|
||||
}
|
||||
return skills;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a list of all buff types available.
|
||||
*/
|
||||
public List<String> getSkillTypes()
|
||||
{
|
||||
List<String> skillTypes = new ArrayList<>();
|
||||
for (BuffSkillHolder skill : _availableBuffs.values())
|
||||
{
|
||||
if (!skillTypes.contains(skill.getType()))
|
||||
{
|
||||
skillTypes.add(skill.getType());
|
||||
}
|
||||
}
|
||||
return skillTypes;
|
||||
}
|
||||
|
||||
public BuffSkillHolder getAvailableBuff(int skillId)
|
||||
{
|
||||
return _availableBuffs.get(skillId);
|
||||
}
|
||||
|
||||
public static SchemeBufferTable getInstance()
|
||||
{
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
private static class SingletonHolder
|
||||
{
|
||||
protected static final SchemeBufferTable INSTANCE = new SchemeBufferTable();
|
||||
}
|
||||
}
|
@@ -83,6 +83,7 @@ public enum InstanceType
|
||||
L2FortDoormenInstance(L2DoormenInstance),
|
||||
// Custom
|
||||
L2ClassMasterInstance(L2NpcInstance),
|
||||
L2SchemeBufferInstance(L2Npc),
|
||||
L2EventMobInstance(L2Npc);
|
||||
|
||||
private final InstanceType _parent;
|
||||
|
@@ -0,0 +1,450 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
package com.l2jmobius.gameserver.model.actor.instance;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import com.l2jmobius.Config;
|
||||
import com.l2jmobius.gameserver.data.xml.impl.SkillData;
|
||||
import com.l2jmobius.gameserver.datatables.SchemeBufferTable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Summon;
|
||||
import com.l2jmobius.gameserver.model.actor.templates.L2NpcTemplate;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage;
|
||||
|
||||
public class L2SchemeBufferInstance extends L2Npc
|
||||
{
|
||||
private static final int PAGE_LIMIT = 6;
|
||||
|
||||
public L2SchemeBufferInstance(L2NpcTemplate template)
|
||||
{
|
||||
super(template);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBypassFeedback(L2PcInstance player, String command)
|
||||
{
|
||||
StringTokenizer st = new StringTokenizer(command, " ");
|
||||
String currentCommand = st.nextToken();
|
||||
|
||||
if (currentCommand.startsWith("menu"))
|
||||
{
|
||||
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
|
||||
html.setFile(player, getHtmlPath(getId(), 0));
|
||||
html.replace("%objectId%", getObjectId());
|
||||
player.sendPacket(html);
|
||||
}
|
||||
else if (currentCommand.startsWith("cleanup"))
|
||||
{
|
||||
player.stopAllEffects();
|
||||
|
||||
final L2Summon summon = player.getPet();
|
||||
if (summon != null)
|
||||
{
|
||||
summon.stopAllEffects();
|
||||
}
|
||||
|
||||
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
|
||||
html.setFile(player, getHtmlPath(getId(), 0));
|
||||
html.replace("%objectId%", getObjectId());
|
||||
player.sendPacket(html);
|
||||
}
|
||||
else if (currentCommand.startsWith("heal"))
|
||||
{
|
||||
player.setCurrentHpMp(player.getMaxHp(), player.getMaxMp());
|
||||
player.setCurrentCp(player.getMaxCp());
|
||||
|
||||
final L2Summon summon = player.getPet();
|
||||
if (summon != null)
|
||||
{
|
||||
summon.setCurrentHpMp(summon.getMaxHp(), summon.getMaxMp());
|
||||
}
|
||||
|
||||
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
|
||||
html.setFile(player, getHtmlPath(getId(), 0));
|
||||
html.replace("%objectId%", getObjectId());
|
||||
player.sendPacket(html);
|
||||
}
|
||||
else if (currentCommand.startsWith("support"))
|
||||
{
|
||||
showGiveBuffsWindow(player);
|
||||
}
|
||||
else if (currentCommand.startsWith("givebuffs"))
|
||||
{
|
||||
final String schemeName = st.nextToken();
|
||||
final int cost = Integer.parseInt(st.nextToken());
|
||||
|
||||
L2Character target = null;
|
||||
if (st.hasMoreTokens())
|
||||
{
|
||||
final String targetType = st.nextToken();
|
||||
if ((targetType != null) && targetType.equalsIgnoreCase("pet"))
|
||||
{
|
||||
target = player.getPet();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
target = player;
|
||||
}
|
||||
|
||||
if (target == null)
|
||||
{
|
||||
player.sendMessage("You don't have a pet.");
|
||||
}
|
||||
else if ((cost == 0) || player.reduceAdena("NPC Buffer", cost, this, true))
|
||||
{
|
||||
for (int skillId : SchemeBufferTable.getInstance().getScheme(player.getObjectId(), schemeName))
|
||||
{
|
||||
SkillData.getInstance().getSkill(skillId, SkillData.getInstance().getMaxLevel(skillId)).applyEffects(this, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (currentCommand.startsWith("editschemes"))
|
||||
{
|
||||
showEditSchemeWindow(player, st.nextToken(), st.nextToken(), Integer.parseInt(st.nextToken()));
|
||||
}
|
||||
else if (currentCommand.startsWith("skill"))
|
||||
{
|
||||
final String groupType = st.nextToken();
|
||||
final String schemeName = st.nextToken();
|
||||
|
||||
final int skillId = Integer.parseInt(st.nextToken());
|
||||
final int page = Integer.parseInt(st.nextToken());
|
||||
|
||||
final List<Integer> skills = SchemeBufferTable.getInstance().getScheme(player.getObjectId(), schemeName);
|
||||
|
||||
if (currentCommand.startsWith("skillselect") && !schemeName.equalsIgnoreCase("none"))
|
||||
{
|
||||
if (skills.size() < player.getStat().getMaxBuffCount())
|
||||
{
|
||||
skills.add(skillId);
|
||||
}
|
||||
else
|
||||
{
|
||||
player.sendMessage("This scheme has reached the maximum amount of buffs.");
|
||||
}
|
||||
}
|
||||
else if (currentCommand.startsWith("skillunselect"))
|
||||
{
|
||||
skills.remove(Integer.valueOf(skillId));
|
||||
}
|
||||
|
||||
showEditSchemeWindow(player, groupType, schemeName, page);
|
||||
}
|
||||
else if (currentCommand.startsWith("createscheme"))
|
||||
{
|
||||
try
|
||||
{
|
||||
final String schemeName = st.nextToken();
|
||||
if (schemeName.length() > 14)
|
||||
{
|
||||
player.sendMessage("Scheme's name must contain up to 14 chars. Spaces are trimmed.");
|
||||
return;
|
||||
}
|
||||
|
||||
final Map<String, ArrayList<Integer>> schemes = SchemeBufferTable.getInstance().getPlayerSchemes(player.getObjectId());
|
||||
if (schemes != null)
|
||||
{
|
||||
if (schemes.size() == Config.BUFFER_MAX_SCHEMES)
|
||||
{
|
||||
player.sendMessage("Maximum schemes amount is already reached.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (schemes.containsKey(schemeName))
|
||||
{
|
||||
player.sendMessage("The scheme name already exists.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SchemeBufferTable.getInstance().setScheme(player.getObjectId(), schemeName.trim(), new ArrayList<Integer>());
|
||||
showGiveBuffsWindow(player);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
player.sendMessage("Scheme's name must contain up to 14 chars. Spaces are trimmed.");
|
||||
}
|
||||
}
|
||||
else if (currentCommand.startsWith("deletescheme"))
|
||||
{
|
||||
try
|
||||
{
|
||||
final String schemeName = st.nextToken();
|
||||
final Map<String, ArrayList<Integer>> schemes = SchemeBufferTable.getInstance().getPlayerSchemes(player.getObjectId());
|
||||
|
||||
if ((schemes != null) && schemes.containsKey(schemeName))
|
||||
{
|
||||
schemes.remove(schemeName);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
player.sendMessage("This scheme name is invalid.");
|
||||
}
|
||||
showGiveBuffsWindow(player);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHtmlPath(int npcId, int val)
|
||||
{
|
||||
String filename = "";
|
||||
if (val == 0)
|
||||
{
|
||||
filename = "" + npcId;
|
||||
}
|
||||
else
|
||||
{
|
||||
filename = npcId + "-" + val;
|
||||
}
|
||||
|
||||
return "data/html/mods/SchemeBuffer/" + filename + ".htm";
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an html packet to player with Give Buffs menu info for player and pet, depending on targetType parameter {player, pet}
|
||||
* @param player : The player to make checks on.
|
||||
*/
|
||||
private void showGiveBuffsWindow(L2PcInstance player)
|
||||
{
|
||||
final StringBuilder sb = new StringBuilder(200);
|
||||
|
||||
final Map<String, ArrayList<Integer>> schemes = SchemeBufferTable.getInstance().getPlayerSchemes(player.getObjectId());
|
||||
if ((schemes == null) || schemes.isEmpty())
|
||||
{
|
||||
sb.append("<font color=\"LEVEL\">You haven't defined any scheme.</font>");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Map.Entry<String, ArrayList<Integer>> scheme : schemes.entrySet())
|
||||
{
|
||||
final int cost = getFee(scheme.getValue());
|
||||
sb.append("<font color=\"LEVEL\">" + scheme.getKey() + " [" + scheme.getValue().size() + " / " + player.getStat().getMaxBuffCount() + "]" + ((cost > 0) ? " - cost: " + NumberFormat.getInstance(Locale.ENGLISH).format(cost) : "") + "</font><br1>");
|
||||
sb.append("<a action=\"bypass -h npc_%objectId%_givebuffs " + scheme.getKey() + " " + cost + "\">Use on Me</a> | ");
|
||||
sb.append("<a action=\"bypass -h npc_%objectId%_givebuffs " + scheme.getKey() + " " + cost + " pet\">Use on Pet</a> | ");
|
||||
sb.append("<a action=\"bypass -h npc_%objectId%_editschemes Buffs " + scheme.getKey() + " 1\">Edit</a> | ");
|
||||
sb.append("<a action=\"bypass -h npc_%objectId%_deletescheme " + scheme.getKey() + "\">Delete</a><br>");
|
||||
}
|
||||
}
|
||||
|
||||
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
|
||||
html.setFile(player, getHtmlPath(getId(), 1));
|
||||
html.replace("%schemes%", sb.toString());
|
||||
html.replace("%max_schemes%", Config.BUFFER_MAX_SCHEMES);
|
||||
html.replace("%objectId%", getObjectId());
|
||||
player.sendPacket(html);
|
||||
}
|
||||
|
||||
/**
|
||||
* This sends an html packet to player with Edit Scheme Menu info. This allows player to edit each created scheme (add/delete skills)
|
||||
* @param player : The player to make checks on.
|
||||
* @param groupType : The group of skills to select.
|
||||
* @param schemeName : The scheme to make check.
|
||||
* @param page The page.
|
||||
*/
|
||||
private void showEditSchemeWindow(L2PcInstance player, String groupType, String schemeName, int page)
|
||||
{
|
||||
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
|
||||
final List<Integer> schemeSkills = SchemeBufferTable.getInstance().getScheme(player.getObjectId(), schemeName);
|
||||
|
||||
html.setFile(player, getHtmlPath(getId(), 2));
|
||||
html.replace("%schemename%", schemeName);
|
||||
html.replace("%count%", schemeSkills.size() + " / " + player.getStat().getMaxBuffCount());
|
||||
html.replace("%typesframe%", getTypesFrame(groupType, schemeName));
|
||||
html.replace("%skilllistframe%", getGroupSkillList(player, groupType, schemeName, page));
|
||||
html.replace("%objectId%", getObjectId());
|
||||
player.sendPacket(html);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param player : The player to make checks on.
|
||||
* @param groupType : The group of skills to select.
|
||||
* @param schemeName : The scheme to make check.
|
||||
* @param page The page.
|
||||
* @return a String representing skills available to selection for a given groupType.
|
||||
*/
|
||||
private String getGroupSkillList(L2PcInstance player, String groupType, String schemeName, int page)
|
||||
{
|
||||
// Retrieve the entire skills list based on group type.
|
||||
List<Integer> skills = SchemeBufferTable.getInstance().getSkillsIdsByType(groupType);
|
||||
if (skills.isEmpty())
|
||||
{
|
||||
return "That group doesn't contain any skills.";
|
||||
}
|
||||
|
||||
// Calculate page number.
|
||||
final int max = countPagesNumber(skills.size(), PAGE_LIMIT);
|
||||
if (page > max)
|
||||
{
|
||||
page = max;
|
||||
}
|
||||
|
||||
// Cut skills list up to page number.
|
||||
skills = skills.subList((page - 1) * PAGE_LIMIT, Math.min(page * PAGE_LIMIT, skills.size()));
|
||||
|
||||
final List<Integer> schemeSkills = SchemeBufferTable.getInstance().getScheme(player.getObjectId(), schemeName);
|
||||
final StringBuilder sb = new StringBuilder(skills.size() * 150);
|
||||
|
||||
int row = 0;
|
||||
for (int skillId : skills)
|
||||
{
|
||||
sb.append(((row % 2) == 0 ? "<table width=\"280\" bgcolor=\"000000\"><tr>" : "<table width=\"280\"><tr>"));
|
||||
|
||||
if (skillId < 100)
|
||||
{
|
||||
if (schemeSkills.contains(skillId))
|
||||
{
|
||||
sb.append("<td height=40 width=40><img src=\"icon.skill00" + skillId + "\" width=32 height=32></td><td width=190>" + SkillData.getInstance().getSkill(skillId, 1).getName() + "<br1><font color=\"B09878\">" + SchemeBufferTable.getInstance().getAvailableBuff(skillId).getDescription() + "</font></td><td><button value=\" \" action=\"bypass -h npc_%objectId%_skillunselect " + groupType + " " + schemeName + " " + skillId + " " + page + "\" width=32 height=32 back=\"L2UI_CH3.mapbutton_zoomout2\" fore=\"L2UI_CH3.mapbutton_zoomout1\"></td>");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("<td height=40 width=40><img src=\"icon.skill00" + skillId + "\" width=32 height=32></td><td width=190>" + SkillData.getInstance().getSkill(skillId, 1).getName() + "<br1><font color=\"B09878\">" + SchemeBufferTable.getInstance().getAvailableBuff(skillId).getDescription() + "</font></td><td><button value=\" \" action=\"bypass -h npc_%objectId%_skillselect " + groupType + " " + schemeName + " " + skillId + " " + page + "\" width=32 height=32 back=\"L2UI_CH3.mapbutton_zoomin2\" fore=\"L2UI_CH3.mapbutton_zoomin1\"></td>");
|
||||
}
|
||||
}
|
||||
else if (skillId < 1000)
|
||||
{
|
||||
if (schemeSkills.contains(skillId))
|
||||
{
|
||||
sb.append("<td height=40 width=40><img src=\"icon.skill0" + skillId + "\" width=32 height=32></td><td width=190>" + SkillData.getInstance().getSkill(skillId, 1).getName() + "<br1><font color=\"B09878\">" + SchemeBufferTable.getInstance().getAvailableBuff(skillId).getDescription() + "</font></td><td><button value=\" \" action=\"bypass -h npc_%objectId%_skillunselect " + groupType + " " + schemeName + " " + skillId + " " + page + "\" width=32 height=32 back=\"L2UI_CH3.mapbutton_zoomout2\" fore=\"L2UI_CH3.mapbutton_zoomout1\"></td>");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("<td height=40 width=40><img src=\"icon.skill0" + skillId + "\" width=32 height=32></td><td width=190>" + SkillData.getInstance().getSkill(skillId, 1).getName() + "<br1><font color=\"B09878\">" + SchemeBufferTable.getInstance().getAvailableBuff(skillId).getDescription() + "</font></td><td><button value=\" \" action=\"bypass -h npc_%objectId%_skillselect " + groupType + " " + schemeName + " " + skillId + " " + page + "\" width=32 height=32 back=\"L2UI_CH3.mapbutton_zoomin2\" fore=\"L2UI_CH3.mapbutton_zoomin1\"></td>");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (schemeSkills.contains(skillId))
|
||||
{
|
||||
sb.append("<td height=40 width=40><img src=\"icon.skill" + skillId + "\" width=32 height=32></td><td width=190>" + SkillData.getInstance().getSkill(skillId, 1).getName() + "<br1><font color=\"B09878\">" + SchemeBufferTable.getInstance().getAvailableBuff(skillId).getDescription() + "</font></td><td height=40 width=40><button value=\" \" action=\"bypass -h npc_%objectId%_skillunselect " + groupType + " " + schemeName + " " + skillId + " " + page + "\" width=32 height=32 back=\"L2UI_CH3.mapbutton_zoomout2\" fore=\"L2UI_CH3.mapbutton_zoomout1\"></td>");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("<td height=40 width=40><img src=\"icon.skill" + skillId + "\" width=32 height=32></td><td width=190>" + SkillData.getInstance().getSkill(skillId, 1).getName() + "<br1><font color=\"B09878\">" + SchemeBufferTable.getInstance().getAvailableBuff(skillId).getDescription() + "</font></td><td height=40 width=40><button value=\" \" action=\"bypass -h npc_%objectId%_skillselect " + groupType + " " + schemeName + " " + skillId + " " + page + "\" width=32 height=32 back=\"L2UI_CH3.mapbutton_zoomin2\" fore=\"L2UI_CH3.mapbutton_zoomin1\"></td>");
|
||||
}
|
||||
}
|
||||
|
||||
sb.append("</tr></table><img src=\"L2UI.SquareGray\" width=277 height=1>");
|
||||
row++;
|
||||
}
|
||||
|
||||
// Build page footer.
|
||||
sb.append("<br><img src=\"L2UI.SquareGray\" width=277 height=1><table width=\"100%\" bgcolor=000000><tr>");
|
||||
|
||||
if (page > 1)
|
||||
{
|
||||
sb.append("<td align=left width=70><a action=\"bypass -h npc_" + getObjectId() + "_editschemes " + groupType + " " + schemeName + " " + (page - 1) + "\">Previous</a></td>");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("<td align=left width=70>Previous</td>");
|
||||
}
|
||||
|
||||
sb.append("<td align=center width=100>Page " + page + "</td>");
|
||||
|
||||
if (page < max)
|
||||
{
|
||||
sb.append("<td align=right width=70><a action=\"bypass -h npc_" + getObjectId() + "_editschemes " + groupType + " " + schemeName + " " + (page + 1) + "\">Next</a></td>");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("<td align=right width=70>Next</td>");
|
||||
}
|
||||
|
||||
sb.append("</tr></table><img src=\"L2UI.SquareGray\" width=277 height=1>");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param groupType : The group of skills to select.
|
||||
* @param schemeName : The scheme to make check.
|
||||
* @return a string representing all groupTypes available. The group currently on selection isn't linkable.
|
||||
*/
|
||||
private static String getTypesFrame(String groupType, String schemeName)
|
||||
{
|
||||
final StringBuilder sb = new StringBuilder(500);
|
||||
sb.append("<table>");
|
||||
|
||||
int count = 0;
|
||||
for (String type : SchemeBufferTable.getInstance().getSkillTypes())
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
sb.append("<tr>");
|
||||
}
|
||||
|
||||
if (groupType.equalsIgnoreCase(type))
|
||||
{
|
||||
sb.append("<td width=65>" + type + "</td>");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("<td width=65><a action=\"bypass -h npc_%objectId%_editschemes " + type + " " + schemeName + " 1\">" + type + "</a></td>");
|
||||
}
|
||||
|
||||
count++;
|
||||
if (count == 4)
|
||||
{
|
||||
sb.append("</tr>");
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sb.toString().endsWith("</tr>"))
|
||||
{
|
||||
sb.append("</tr>");
|
||||
}
|
||||
|
||||
sb.append("</table>");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list : A list of skill ids.
|
||||
* @return a global fee for all skills contained in list.
|
||||
*/
|
||||
private static int getFee(ArrayList<Integer> list)
|
||||
{
|
||||
if (Config.BUFFER_STATIC_BUFF_COST > 0)
|
||||
{
|
||||
return list.size() * Config.BUFFER_STATIC_BUFF_COST;
|
||||
}
|
||||
|
||||
int fee = 0;
|
||||
for (int sk : list)
|
||||
{
|
||||
fee += SchemeBufferTable.getInstance().getAvailableBuff(sk).getValue();
|
||||
}
|
||||
|
||||
return fee;
|
||||
}
|
||||
|
||||
private static int countPagesNumber(int objectsSize, int pageSize)
|
||||
{
|
||||
return (objectsSize / pageSize) + ((objectsSize % pageSize) == 0 ? 0 : 1);
|
||||
}
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
package com.l2jmobius.gameserver.model.holders;
|
||||
|
||||
/**
|
||||
* A container used for schemes buffer.
|
||||
*/
|
||||
public final class BuffSkillHolder extends IntIntHolder
|
||||
{
|
||||
private final String _type;
|
||||
private final String _description;
|
||||
|
||||
public BuffSkillHolder(int id, int price, String type, String description)
|
||||
{
|
||||
super(id, price);
|
||||
|
||||
_type = type;
|
||||
_description = description;
|
||||
}
|
||||
|
||||
public final String getType()
|
||||
{
|
||||
return _type;
|
||||
}
|
||||
|
||||
public final String getDescription()
|
||||
{
|
||||
return _description;
|
||||
}
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
package com.l2jmobius.gameserver.model.holders;
|
||||
|
||||
import com.l2jmobius.gameserver.data.xml.impl.SkillData;
|
||||
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||
|
||||
/**
|
||||
* A generic int/int container.
|
||||
*/
|
||||
public class IntIntHolder
|
||||
{
|
||||
private int _id;
|
||||
private int _value;
|
||||
|
||||
public IntIntHolder(int id, int value)
|
||||
{
|
||||
_id = id;
|
||||
_value = value;
|
||||
}
|
||||
|
||||
public int getId()
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
|
||||
public int getValue()
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
public void setId(int id)
|
||||
{
|
||||
_id = id;
|
||||
}
|
||||
|
||||
public void setValue(int value)
|
||||
{
|
||||
_value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the L2Skill associated to the id/value.
|
||||
*/
|
||||
public final Skill getSkill()
|
||||
{
|
||||
return SkillData.getInstance().getSkill(_id, _value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getClass().getSimpleName() + ": Id: " + _id + ", Value: " + _value;
|
||||
}
|
||||
}
|
5
L2J_Mobius_Classic_2.0_Zaken/dist/db_installer/sql/game/buffer_schemes.sql
vendored
Normal file
5
L2J_Mobius_Classic_2.0_Zaken/dist/db_installer/sql/game/buffer_schemes.sql
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
CREATE TABLE IF NOT EXISTS `buffer_schemes` (
|
||||
`object_id` INT UNSIGNED NOT NULL DEFAULT '0',
|
||||
`scheme_name` VARCHAR(16) NOT NULL DEFAULT 'default',
|
||||
`skills` VARCHAR(200) NOT NULL
|
||||
);
|
10
L2J_Mobius_Classic_2.0_Zaken/dist/game/config/Custom/ShemeBuffer.ini
vendored
Normal file
10
L2J_Mobius_Classic_2.0_Zaken/dist/game/config/Custom/ShemeBuffer.ini
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
#=============================================================
|
||||
# Buffer
|
||||
#=============================================================
|
||||
# Also check data\SchemeBufferSkills.xml
|
||||
|
||||
# Maximum number of available schemes per player.
|
||||
BufferMaxSchemesPerChar = 4
|
||||
|
||||
# Static cost of buffs ; override skills price if different of -1.
|
||||
BufferStaticCostPerBuff = -1
|
69
L2J_Mobius_Classic_2.0_Zaken/dist/game/data/SchemeBufferSkills.xml
vendored
Normal file
69
L2J_Mobius_Classic_2.0_Zaken/dist/game/data/SchemeBufferSkills.xml
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<list xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="xsd/SchemeBufferSkills.xsd">
|
||||
<category type="Buffs">
|
||||
<buff id="1035" price="0" desc="Increases resistance to mental attacks." /> <!-- Mental Shield -->
|
||||
<buff id="1036" price="0" desc="Increases M. Def." /> <!-- Magic Barrier -->
|
||||
<buff id="1040" price="0" desc="Increases P. Def." /> <!-- Shield -->
|
||||
<buff id="1045" price="0" desc="Increases maximum HP." /> <!-- Blessed Body -->
|
||||
<buff id="1048" price="0" desc="Increases maximum MP." /> <!-- Blessed Soul -->
|
||||
<buff id="1059" price="0" desc="Increases M. Atk." /> <!-- Empower -->
|
||||
<buff id="1062" price="0" desc="Reduces def. and increase atk. power." /> <!-- Berserker Spirit -->
|
||||
<buff id="1068" price="0" desc="Increases P. Atk." /> <!-- Might -->
|
||||
<buff id="1077" price="0" desc="Increases critical attack rate." /> <!-- Focus -->
|
||||
<buff id="1078" price="0" desc="Increases magic concentration." /> <!-- Concentration -->
|
||||
<buff id="1085" price="0" desc="Increases Casting Spd." /> <!-- Acumen -->
|
||||
<buff id="1086" price="0" desc="Increases Atk. Spd." /> <!-- Haste -->
|
||||
<buff id="1087" price="0" desc="Increases Evasion." /> <!-- Agility -->
|
||||
<buff id="1204" price="0" desc="Increases Speed." /> <!-- Wind Walk -->
|
||||
<buff id="1240" price="0" desc="Increases Accuracy." /> <!-- Guidance -->
|
||||
<buff id="1242" price="0" desc="Increases critical attack." /> <!-- Death Whisper -->
|
||||
<buff id="1243" price="0" desc="Increases shield defense rate." /> <!-- Bless Shield -->
|
||||
<buff id="1259" price="0" desc="Increases resistance to stun attack." /> <!-- Resist Shock -->
|
||||
<buff id="1268" price="0" desc="Restores HP using inflicted damage." /> <!-- Vampiric Rage -->
|
||||
<buff id="1303" price="0" desc="Increases crit. rate of magic attacks." /> <!-- Wild Magic -->
|
||||
<buff id="1304" price="0" desc="Increases shield defense power." /> <!-- Advanced Block -->
|
||||
<buff id="1352" price="0" desc="Increases resistance to atures." /> <!-- Elemental Protection -->
|
||||
<buff id="1353" price="0" desc="Increases resistance to dark attack." /> <!-- Divine Protection -->
|
||||
<buff id="1354" price="0" desc="Increases resistance to de-buff attack." /> <!-- Arcane Protection -->
|
||||
<buff id="1355" price="0" desc="Increases mage abilities." /> <!-- Prophecy of Water -->
|
||||
<buff id="1356" price="0" desc="Increases fighter abilities." /> <!-- Prophecy of Fire -->
|
||||
<buff id="1357" price="0" desc="Increases dagger abilities." /> <!-- Prophecy of Wind -->
|
||||
<buff id="1363" price="0" desc="Increases combat abilities." /> <!-- Chant of Victory -->
|
||||
<buff id="1388" price="0" desc="Increases P. Atk." /> <!-- Greater Might -->
|
||||
<buff id="1389" price="0" desc="Increases P. Def." /> <!-- Greater Shield -->
|
||||
<buff id="1390" price="0" desc="Increases P. Atk." /> <!-- War Chant -->
|
||||
<buff id="1391" price="0" desc="Increases P. Def." /> <!-- Earth Chant -->
|
||||
<buff id="1397" price="0" desc="Decreases MP consumption rate." /> <!-- Clarity -->
|
||||
<buff id="1413" price="0" desc="Increases mage abilities." /> <!-- Magnus' Chant -->
|
||||
</category>
|
||||
<category type="Dances">
|
||||
<buff id="271" price="0" desc="Increases P. Atk." /> <!-- Dance of the Warrior -->
|
||||
<buff id="272" price="0" desc="Increases Accuracy." /> <!-- Dance of Inspiration -->
|
||||
<buff id="273" price="0" desc="Increases M. Atk." /> <!-- Dance of the Mystic -->
|
||||
<buff id="274" price="0" desc="Increases critical damage." /> <!-- Dance of Fire -->
|
||||
<buff id="275" price="0" desc="Increases attack speed." /> <!-- Dance of Fury -->
|
||||
<buff id="276" price="0" desc="Increases Casting Spd." /> <!-- Dance of Concentration -->
|
||||
<buff id="277" price="0" desc="Sacred power to physical attack." /> <!-- Dance of Light -->
|
||||
<buff id="307" price="0" desc="Increases water resistance." /> <!-- Dance of Aqua Guard -->
|
||||
<buff id="309" price="0" desc="Increases earth resistance." /> <!-- Dance of Earth Guard -->
|
||||
<buff id="310" price="0" desc="Restores HP by inflicted damage." /> <!-- Dance of the Vampire -->
|
||||
<buff id="311" price="0" desc="Increases resistance to terrain damage." /> <!-- Dance of Protection -->
|
||||
<buff id="365" price="0" desc="Increases rate of magic crit. damage." /> <!-- Siren's Dance -->
|
||||
</category>
|
||||
<category type="Songs">
|
||||
<buff id="264" price="0" desc="Increases P. Def." /> <!-- Song of Earth -->
|
||||
<buff id="265" price="0" desc="Increases HP regeneration." /> <!-- Song of Life -->
|
||||
<buff id="266" price="0" desc="Increases Evasion." /> <!-- Song of Water -->
|
||||
<buff id="267" price="0" desc="Increases M. Def." /> <!-- Song of Warding -->
|
||||
<buff id="268" price="0" desc="Increases movement." /> <!-- Song of Wind -->
|
||||
<buff id="269" price="0" desc="Increases critical rate." /> <!-- Song of Hunter -->
|
||||
<buff id="270" price="0" desc="Increases resistance to dark magic." /> <!-- Song of Invocation -->
|
||||
<buff id="304" price="0" desc="Increases maximum HP." /> <!-- Song of Vitality -->
|
||||
<buff id="305" price="0" desc="Reflects damage received." /> <!-- Song of Vengeance -->
|
||||
<buff id="306" price="0" desc="Increases resistance to fire." /> <!-- Song of Flame Guard -->
|
||||
<buff id="308" price="0" desc="Increases resistance to wind." /> <!-- Song of Storm Guard -->
|
||||
<buff id="349" price="0" desc="Decreases re-use time." /> <!-- Song of Renewal -->
|
||||
<buff id="363" price="0" desc="Increases MP regeneration rate." /> <!-- Song of Meditation -->
|
||||
<buff id="364" price="0" desc="Decreases re-use time of physical skills." /> <!-- Song of Champion -->
|
||||
</category>
|
||||
</list>
|
14
L2J_Mobius_Classic_2.0_Zaken/dist/game/data/html/mods/SchemeBuffer/50008-1.htm
vendored
Normal file
14
L2J_Mobius_Classic_2.0_Zaken/dist/game/data/html/mods/SchemeBuffer/50008-1.htm
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<html><body>
|
||||
<font color="LEVEL">You can create up to %max_schemes% schemes.</font> Is it clear for you?<br1>
|
||||
If not, read until you get it! I can't afford idiots...<br>
|
||||
You can register a new scheme filling this form, here!
|
||||
<center><table width=220>
|
||||
<tr>
|
||||
<td width="140"><edit var="name" width=140 height=15></td>
|
||||
<td width="60"><button value="Create" action="bypass -h npc_%objectId%_createscheme $name" width=75 height=21 back="L2UI_ch3.Btn1_normalOn" fore="L2UI_ch3.Btn1_normal"></td>
|
||||
</tr>
|
||||
</table></center><br>
|
||||
Here are listed your schemes and their fee.<br>
|
||||
%schemes%<br>
|
||||
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h npc_%objectId%_menu">Back</Button>
|
||||
</body></html>
|
8
L2J_Mobius_Classic_2.0_Zaken/dist/game/data/html/mods/SchemeBuffer/50008-2.htm
vendored
Normal file
8
L2J_Mobius_Classic_2.0_Zaken/dist/game/data/html/mods/SchemeBuffer/50008-2.htm
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
<html><body>
|
||||
<font color="LEVEL">%schemename%</font> scheme holds %count% buffs.<br>
|
||||
<center>
|
||||
%typesframe%<br>
|
||||
%skilllistframe%<br>
|
||||
</center>
|
||||
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h npc_%objectId%_support">Back</Button>
|
||||
</body></html>
|
8
L2J_Mobius_Classic_2.0_Zaken/dist/game/data/html/mods/SchemeBuffer/50008.htm
vendored
Normal file
8
L2J_Mobius_Classic_2.0_Zaken/dist/game/data/html/mods/SchemeBuffer/50008.htm
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
<html><body>
|
||||
Hello stranger!<br>
|
||||
Yup, you're right, I decided to share some of my powerful buffs in order to improve your pew-pew-bum-zap abilities.<br>
|
||||
What can I do for you?<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_support">Magic support</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_heal">Heal me and my pet</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_cleanup">Cleanup all effects on me and my pet</Button>
|
||||
</body></html>
|
21
L2J_Mobius_Classic_2.0_Zaken/dist/game/data/stats/npcs/custom/SchemeBuffer.xml
vendored
Normal file
21
L2J_Mobius_Classic_2.0_Zaken/dist/game/data/stats/npcs/custom/SchemeBuffer.xml
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<list xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../xsd/npcs.xsd">
|
||||
<npc id="50008" displayId="9000" type="L2SchemeBuffer" name="Rosalia" usingServerSideName="true" title="Scheme Buffer" usingServerSideTitle="true">
|
||||
<race>HUMAN</race>
|
||||
<sex>FEMALE</sex>
|
||||
<stats>
|
||||
<vitals hp="2444.46819" hpRegen="7.5" mp="1345.8" mpRegen="2.7" />
|
||||
<attack physical="688.86373" magical="470.40463" random="30" critical="4" accuracy="95" attackSpeed="253" type="SWORD" range="40" distance="80" width="120" />
|
||||
<defence physical="295.91597" magical="216.53847" />
|
||||
<speed>
|
||||
<walk ground="50" />
|
||||
<run ground="120" />
|
||||
</speed>
|
||||
</stats>
|
||||
<status attackable="false" />
|
||||
<collision>
|
||||
<radius normal="11" />
|
||||
<height normal="22.25" />
|
||||
</collision>
|
||||
</npc>
|
||||
</list>
|
32
L2J_Mobius_Classic_2.0_Zaken/dist/game/data/xsd/SchemeBufferSkills.xsd
vendored
Normal file
32
L2J_Mobius_Classic_2.0_Zaken/dist/game/data/xsd/SchemeBufferSkills.xsd
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:element name="list">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="category" maxOccurs="unbounded" minOccurs="0">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Magnus' Chant Siren's Dance Song of Champion</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="buff" maxOccurs="unbounded" minOccurs="0">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Mental Shield Magic Barrier Shield Blessed Body Blessed Soul Empower Berserker Spirit Might Focus Concentration Acumen Haste Agility Wind Walk Guidance Death Whisper Bless Shield Resist Shock Vampiric Rage Wild Magic Advanced Block Elemental Protection Divine Protection Arcane Protection Prophecy of Water Prophecy of Fire Prophecy of Wind Chant of Victory Greater Might Greater Shield War Chant Earth Chant Clarity Dance of the Warrior Dance of Inspiration Dance of the Mystic Dance of Fire Dance of Fury Dance of Concentration Dance of Light Dance of Aqua Guard Dance of Earth Guard Dance of the Vampire Dance of Protection Song of Earth Song of Life Song of Water Song of Warding Song of Wind Song of Hunter Song of Invocation Song of Vitality Song of Vengeance Song of Flame Guard Song of Storm Guard Song of Renewal Song of Meditation</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:complexType>
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="xs:string">
|
||||
<xs:attribute type="xs:short" name="id" use="optional"/>
|
||||
<xs:attribute type="xs:byte" name="price" use="optional"/>
|
||||
<xs:attribute type="xs:string" name="desc" use="optional"/>
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute type="xs:string" name="type" use="optional"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
@@ -133,6 +133,7 @@ public final class Config
|
||||
public static final String CUSTOM_SCREEN_WELCOME_MESSAGE_CONFIG_FILE = "./config/Custom/ScreenWelcomeMessage.ini";
|
||||
public static final String CUSTOM_SELL_BUFFS_CONFIG_FILE = "./config/Custom/SellBuffs.ini";
|
||||
public static final String CUSTOM_SERVER_TIME_CONFIG_FILE = "./config/Custom/ServerTime.ini";
|
||||
public static final String CUSTOM_SCHEME_BUFFER_CONFIG_FILE = "./config/Custom/ShemeBuffer.ini";
|
||||
public static final String CUSTOM_STARTING_LOCATION_CONFIG_FILE = "./config/Custom/StartingLocation.ini";
|
||||
public static final String CUSTOM_VOTE_REWARD_CONFIG_FILE = "./config/Custom/VoteReward.ini";
|
||||
public static final String CUSTOM_WALKER_BOT_PROTECTION_CONFIG_FILE = "./config/Custom/WalkerBotProtection.ini";
|
||||
@@ -1012,6 +1013,8 @@ public final class Config
|
||||
public static boolean OFFLINE_FAME;
|
||||
public static boolean STORE_OFFLINE_TRADE_IN_REALTIME;
|
||||
public static boolean DISPLAY_SERVER_TIME;
|
||||
public static int BUFFER_MAX_SCHEMES;
|
||||
public static int BUFFER_STATIC_BUFF_COST;
|
||||
public static boolean WELCOME_MESSAGE_ENABLED;
|
||||
public static String WELCOME_MESSAGE_TEXT;
|
||||
public static int WELCOME_MESSAGE_TIME;
|
||||
@@ -2776,6 +2779,12 @@ public final class Config
|
||||
|
||||
DISPLAY_SERVER_TIME = ServerTime.getBoolean("DisplayServerTime", false);
|
||||
|
||||
// Load SchemeBuffer config file (if exists)
|
||||
final PropertiesParser SchemeBuffer = new PropertiesParser(CUSTOM_SCHEME_BUFFER_CONFIG_FILE);
|
||||
|
||||
BUFFER_MAX_SCHEMES = SchemeBuffer.getInt("BufferMaxSchemesPerChar", 4);
|
||||
BUFFER_STATIC_BUFF_COST = SchemeBuffer.getInt("BufferStaticCostPerBuff", -1);
|
||||
|
||||
// Load StartingLocation config file (if exists)
|
||||
final PropertiesParser StartingLocation = new PropertiesParser(CUSTOM_STARTING_LOCATION_CONFIG_FILE);
|
||||
|
||||
|
@@ -97,6 +97,7 @@ import com.l2jmobius.gameserver.data.xml.impl.VariationData;
|
||||
import com.l2jmobius.gameserver.datatables.BotReportTable;
|
||||
import com.l2jmobius.gameserver.datatables.EventDroplist;
|
||||
import com.l2jmobius.gameserver.datatables.ItemTable;
|
||||
import com.l2jmobius.gameserver.datatables.SchemeBufferTable;
|
||||
import com.l2jmobius.gameserver.geoengine.GeoEngine;
|
||||
import com.l2jmobius.gameserver.handler.ConditionHandler;
|
||||
import com.l2jmobius.gameserver.handler.DailyMissionHandler;
|
||||
@@ -317,6 +318,7 @@ public class GameServer
|
||||
StaticObjectData.getInstance();
|
||||
ItemAuctionManager.getInstance();
|
||||
CastleManager.getInstance().loadInstances();
|
||||
SchemeBufferTable.getInstance();
|
||||
GrandBossManager.getInstance();
|
||||
EventDroplist.getInstance();
|
||||
CommissionManager.getInstance();
|
||||
|
@@ -26,6 +26,7 @@ import com.l2jmobius.commons.database.DatabaseFactory;
|
||||
import com.l2jmobius.gameserver.data.sql.impl.ClanTable;
|
||||
import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable;
|
||||
import com.l2jmobius.gameserver.datatables.BotReportTable;
|
||||
import com.l2jmobius.gameserver.datatables.SchemeBufferTable;
|
||||
import com.l2jmobius.gameserver.instancemanager.CastleManorManager;
|
||||
import com.l2jmobius.gameserver.instancemanager.CeremonyOfChaosManager;
|
||||
import com.l2jmobius.gameserver.instancemanager.CursedWeaponsManager;
|
||||
@@ -521,6 +522,10 @@ public class Shutdown extends Thread
|
||||
GlobalVariablesManager.getInstance().storeMe();
|
||||
LOGGER.info("Global Variables Manager: Variables saved(" + tc.getEstimatedTimeAndRestartCounter() + "ms).");
|
||||
|
||||
// Schemes save.
|
||||
SchemeBufferTable.getInstance().saveSchemes();
|
||||
LOGGER.info("SchemeBufferTable data has been saved.");
|
||||
|
||||
// Save items on ground before closing
|
||||
if (Config.SAVE_DROPPED_ITEM)
|
||||
{
|
||||
|
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
package com.l2jmobius.gameserver.datatables;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import com.l2jmobius.Config;
|
||||
import com.l2jmobius.commons.database.DatabaseFactory;
|
||||
import com.l2jmobius.gameserver.model.holders.BuffSkillHolder;
|
||||
|
||||
/**
|
||||
* This class loads available skills and stores players' buff schemes into _schemesTable.
|
||||
*/
|
||||
public class SchemeBufferTable
|
||||
{
|
||||
private static final Logger LOGGER = Logger.getLogger(SchemeBufferTable.class.getName());
|
||||
|
||||
private static final String LOAD_SCHEMES = "SELECT * FROM buffer_schemes";
|
||||
private static final String DELETE_SCHEMES = "TRUNCATE TABLE buffer_schemes";
|
||||
private static final String INSERT_SCHEME = "INSERT INTO buffer_schemes (object_id, scheme_name, skills) VALUES (?,?,?)";
|
||||
|
||||
private final Map<Integer, HashMap<String, ArrayList<Integer>>> _schemesTable = new ConcurrentHashMap<>();
|
||||
private final Map<Integer, BuffSkillHolder> _availableBuffs = new LinkedHashMap<>();
|
||||
|
||||
public SchemeBufferTable()
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
try (Connection con = DatabaseFactory.getInstance().getConnection())
|
||||
{
|
||||
PreparedStatement st = con.prepareStatement(LOAD_SCHEMES);
|
||||
ResultSet rs = st.executeQuery();
|
||||
|
||||
while (rs.next())
|
||||
{
|
||||
final int objectId = rs.getInt("object_id");
|
||||
|
||||
final String schemeName = rs.getString("scheme_name");
|
||||
final String[] skills = rs.getString("skills").split(",");
|
||||
|
||||
ArrayList<Integer> schemeList = new ArrayList<>();
|
||||
|
||||
for (String skill : skills)
|
||||
{
|
||||
// Don't feed the skills list if the list is empty.
|
||||
if (skill.isEmpty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
schemeList.add(Integer.valueOf(skill));
|
||||
}
|
||||
|
||||
setScheme(objectId, schemeName, schemeList);
|
||||
count++;
|
||||
}
|
||||
|
||||
rs.close();
|
||||
st.close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.warning("SchemeBufferTable: Failed to load buff schemes : " + e);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder db = dbf.newDocumentBuilder();
|
||||
Document doc = db.parse(new File("./data/SchemeBufferSkills.xml"));
|
||||
|
||||
final Node n = doc.getFirstChild();
|
||||
|
||||
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
|
||||
{
|
||||
if (!d.getNodeName().equalsIgnoreCase("category"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
final String category = d.getAttributes().getNamedItem("type").getNodeValue();
|
||||
|
||||
for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
|
||||
{
|
||||
if (!c.getNodeName().equalsIgnoreCase("buff"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
final NamedNodeMap attrs = c.getAttributes();
|
||||
final int skillId = Integer.parseInt(attrs.getNamedItem("id").getNodeValue());
|
||||
|
||||
_availableBuffs.put(skillId, new BuffSkillHolder(skillId, Integer.parseInt(attrs.getNamedItem("price").getNodeValue()), category, attrs.getNamedItem("desc").getNodeValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.warning("SchemeBufferTable: Failed to load buff info : " + e);
|
||||
}
|
||||
LOGGER.info("SchemeBufferTable: Loaded " + count + " players schemes and " + _availableBuffs.size() + " available buffs.");
|
||||
}
|
||||
|
||||
public void saveSchemes()
|
||||
{
|
||||
try (Connection con = DatabaseFactory.getInstance().getConnection())
|
||||
{
|
||||
// Delete all entries from database.
|
||||
PreparedStatement st = con.prepareStatement(DELETE_SCHEMES);
|
||||
st.execute();
|
||||
st.close();
|
||||
|
||||
st = con.prepareStatement(INSERT_SCHEME);
|
||||
|
||||
// Save _schemesTable content.
|
||||
for (Map.Entry<Integer, HashMap<String, ArrayList<Integer>>> player : _schemesTable.entrySet())
|
||||
{
|
||||
for (Map.Entry<String, ArrayList<Integer>> scheme : player.getValue().entrySet())
|
||||
{
|
||||
// Build a String composed of skill ids seperated by a ",".
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
for (int skillId : scheme.getValue())
|
||||
{
|
||||
sb.append(skillId + ",");
|
||||
}
|
||||
|
||||
// Delete the last "," : must be called only if there is something to delete !
|
||||
if (sb.length() > 0)
|
||||
{
|
||||
sb.setLength(sb.length() - 1);
|
||||
}
|
||||
|
||||
st.setInt(1, player.getKey());
|
||||
st.setString(2, scheme.getKey());
|
||||
st.setString(3, sb.toString());
|
||||
st.addBatch();
|
||||
}
|
||||
}
|
||||
st.executeBatch();
|
||||
st.close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.warning("BufferTableScheme: Error while saving schemes : " + e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setScheme(int playerId, String schemeName, ArrayList<Integer> list)
|
||||
{
|
||||
if (!_schemesTable.containsKey(playerId))
|
||||
{
|
||||
_schemesTable.put(playerId, new HashMap<String, ArrayList<Integer>>());
|
||||
}
|
||||
else if (_schemesTable.get(playerId).size() >= Config.BUFFER_MAX_SCHEMES)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_schemesTable.get(playerId).put(schemeName, list);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param playerId : The player objectId to check.
|
||||
* @return the list of schemes for a given player.
|
||||
*/
|
||||
public Map<String, ArrayList<Integer>> getPlayerSchemes(int playerId)
|
||||
{
|
||||
return _schemesTable.get(playerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param playerId : The player objectId to check.
|
||||
* @param schemeName : The scheme name to check.
|
||||
* @return the List holding skills for the given scheme name and player, or null (if scheme or player isn't registered).
|
||||
*/
|
||||
public List<Integer> getScheme(int playerId, String schemeName)
|
||||
{
|
||||
if ((_schemesTable.get(playerId) == null) || (_schemesTable.get(playerId).get(schemeName) == null))
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return _schemesTable.get(playerId).get(schemeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param playerId : The player objectId to check.
|
||||
* @param schemeName : The scheme name to check.
|
||||
* @param skillId : The skill id to check.
|
||||
* @return true if the skill is already registered on the scheme, or false otherwise.
|
||||
*/
|
||||
public boolean getSchemeContainsSkill(int playerId, String schemeName, int skillId)
|
||||
{
|
||||
final List<Integer> skills = getScheme(playerId, schemeName);
|
||||
if (skills.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int id : skills)
|
||||
{
|
||||
if (id == skillId)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param groupType : The type of skills to return.
|
||||
* @return a list of skills ids based on the given groupType.
|
||||
*/
|
||||
public List<Integer> getSkillsIdsByType(String groupType)
|
||||
{
|
||||
List<Integer> skills = new ArrayList<>();
|
||||
for (BuffSkillHolder skill : _availableBuffs.values())
|
||||
{
|
||||
if (skill.getType().equalsIgnoreCase(groupType))
|
||||
{
|
||||
skills.add(skill.getId());
|
||||
}
|
||||
}
|
||||
return skills;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a list of all buff types available.
|
||||
*/
|
||||
public List<String> getSkillTypes()
|
||||
{
|
||||
List<String> skillTypes = new ArrayList<>();
|
||||
for (BuffSkillHolder skill : _availableBuffs.values())
|
||||
{
|
||||
if (!skillTypes.contains(skill.getType()))
|
||||
{
|
||||
skillTypes.add(skill.getType());
|
||||
}
|
||||
}
|
||||
return skillTypes;
|
||||
}
|
||||
|
||||
public BuffSkillHolder getAvailableBuff(int skillId)
|
||||
{
|
||||
return _availableBuffs.get(skillId);
|
||||
}
|
||||
|
||||
public static SchemeBufferTable getInstance()
|
||||
{
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
private static class SingletonHolder
|
||||
{
|
||||
protected static final SchemeBufferTable INSTANCE = new SchemeBufferTable();
|
||||
}
|
||||
}
|
@@ -83,6 +83,7 @@ public enum InstanceType
|
||||
L2FortDoormenInstance(L2DoormenInstance),
|
||||
// Custom
|
||||
L2ClassMasterInstance(L2NpcInstance),
|
||||
L2SchemeBufferInstance(L2Npc),
|
||||
L2EventMobInstance(L2Npc);
|
||||
|
||||
private final InstanceType _parent;
|
||||
|
@@ -0,0 +1,450 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
package com.l2jmobius.gameserver.model.actor.instance;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import com.l2jmobius.Config;
|
||||
import com.l2jmobius.gameserver.data.xml.impl.SkillData;
|
||||
import com.l2jmobius.gameserver.datatables.SchemeBufferTable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Summon;
|
||||
import com.l2jmobius.gameserver.model.actor.templates.L2NpcTemplate;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage;
|
||||
|
||||
public class L2SchemeBufferInstance extends L2Npc
|
||||
{
|
||||
private static final int PAGE_LIMIT = 6;
|
||||
|
||||
public L2SchemeBufferInstance(L2NpcTemplate template)
|
||||
{
|
||||
super(template);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBypassFeedback(L2PcInstance player, String command)
|
||||
{
|
||||
StringTokenizer st = new StringTokenizer(command, " ");
|
||||
String currentCommand = st.nextToken();
|
||||
|
||||
if (currentCommand.startsWith("menu"))
|
||||
{
|
||||
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
|
||||
html.setFile(player, getHtmlPath(getId(), 0));
|
||||
html.replace("%objectId%", getObjectId());
|
||||
player.sendPacket(html);
|
||||
}
|
||||
else if (currentCommand.startsWith("cleanup"))
|
||||
{
|
||||
player.stopAllEffects();
|
||||
|
||||
final L2Summon summon = player.getPet();
|
||||
if (summon != null)
|
||||
{
|
||||
summon.stopAllEffects();
|
||||
}
|
||||
|
||||
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
|
||||
html.setFile(player, getHtmlPath(getId(), 0));
|
||||
html.replace("%objectId%", getObjectId());
|
||||
player.sendPacket(html);
|
||||
}
|
||||
else if (currentCommand.startsWith("heal"))
|
||||
{
|
||||
player.setCurrentHpMp(player.getMaxHp(), player.getMaxMp());
|
||||
player.setCurrentCp(player.getMaxCp());
|
||||
|
||||
final L2Summon summon = player.getPet();
|
||||
if (summon != null)
|
||||
{
|
||||
summon.setCurrentHpMp(summon.getMaxHp(), summon.getMaxMp());
|
||||
}
|
||||
|
||||
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
|
||||
html.setFile(player, getHtmlPath(getId(), 0));
|
||||
html.replace("%objectId%", getObjectId());
|
||||
player.sendPacket(html);
|
||||
}
|
||||
else if (currentCommand.startsWith("support"))
|
||||
{
|
||||
showGiveBuffsWindow(player);
|
||||
}
|
||||
else if (currentCommand.startsWith("givebuffs"))
|
||||
{
|
||||
final String schemeName = st.nextToken();
|
||||
final int cost = Integer.parseInt(st.nextToken());
|
||||
|
||||
L2Character target = null;
|
||||
if (st.hasMoreTokens())
|
||||
{
|
||||
final String targetType = st.nextToken();
|
||||
if ((targetType != null) && targetType.equalsIgnoreCase("pet"))
|
||||
{
|
||||
target = player.getPet();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
target = player;
|
||||
}
|
||||
|
||||
if (target == null)
|
||||
{
|
||||
player.sendMessage("You don't have a pet.");
|
||||
}
|
||||
else if ((cost == 0) || player.reduceAdena("NPC Buffer", cost, this, true))
|
||||
{
|
||||
for (int skillId : SchemeBufferTable.getInstance().getScheme(player.getObjectId(), schemeName))
|
||||
{
|
||||
SkillData.getInstance().getSkill(skillId, SkillData.getInstance().getMaxLevel(skillId)).applyEffects(this, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (currentCommand.startsWith("editschemes"))
|
||||
{
|
||||
showEditSchemeWindow(player, st.nextToken(), st.nextToken(), Integer.parseInt(st.nextToken()));
|
||||
}
|
||||
else if (currentCommand.startsWith("skill"))
|
||||
{
|
||||
final String groupType = st.nextToken();
|
||||
final String schemeName = st.nextToken();
|
||||
|
||||
final int skillId = Integer.parseInt(st.nextToken());
|
||||
final int page = Integer.parseInt(st.nextToken());
|
||||
|
||||
final List<Integer> skills = SchemeBufferTable.getInstance().getScheme(player.getObjectId(), schemeName);
|
||||
|
||||
if (currentCommand.startsWith("skillselect") && !schemeName.equalsIgnoreCase("none"))
|
||||
{
|
||||
if (skills.size() < player.getStat().getMaxBuffCount())
|
||||
{
|
||||
skills.add(skillId);
|
||||
}
|
||||
else
|
||||
{
|
||||
player.sendMessage("This scheme has reached the maximum amount of buffs.");
|
||||
}
|
||||
}
|
||||
else if (currentCommand.startsWith("skillunselect"))
|
||||
{
|
||||
skills.remove(Integer.valueOf(skillId));
|
||||
}
|
||||
|
||||
showEditSchemeWindow(player, groupType, schemeName, page);
|
||||
}
|
||||
else if (currentCommand.startsWith("createscheme"))
|
||||
{
|
||||
try
|
||||
{
|
||||
final String schemeName = st.nextToken();
|
||||
if (schemeName.length() > 14)
|
||||
{
|
||||
player.sendMessage("Scheme's name must contain up to 14 chars. Spaces are trimmed.");
|
||||
return;
|
||||
}
|
||||
|
||||
final Map<String, ArrayList<Integer>> schemes = SchemeBufferTable.getInstance().getPlayerSchemes(player.getObjectId());
|
||||
if (schemes != null)
|
||||
{
|
||||
if (schemes.size() == Config.BUFFER_MAX_SCHEMES)
|
||||
{
|
||||
player.sendMessage("Maximum schemes amount is already reached.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (schemes.containsKey(schemeName))
|
||||
{
|
||||
player.sendMessage("The scheme name already exists.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SchemeBufferTable.getInstance().setScheme(player.getObjectId(), schemeName.trim(), new ArrayList<Integer>());
|
||||
showGiveBuffsWindow(player);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
player.sendMessage("Scheme's name must contain up to 14 chars. Spaces are trimmed.");
|
||||
}
|
||||
}
|
||||
else if (currentCommand.startsWith("deletescheme"))
|
||||
{
|
||||
try
|
||||
{
|
||||
final String schemeName = st.nextToken();
|
||||
final Map<String, ArrayList<Integer>> schemes = SchemeBufferTable.getInstance().getPlayerSchemes(player.getObjectId());
|
||||
|
||||
if ((schemes != null) && schemes.containsKey(schemeName))
|
||||
{
|
||||
schemes.remove(schemeName);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
player.sendMessage("This scheme name is invalid.");
|
||||
}
|
||||
showGiveBuffsWindow(player);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHtmlPath(int npcId, int val)
|
||||
{
|
||||
String filename = "";
|
||||
if (val == 0)
|
||||
{
|
||||
filename = "" + npcId;
|
||||
}
|
||||
else
|
||||
{
|
||||
filename = npcId + "-" + val;
|
||||
}
|
||||
|
||||
return "data/html/mods/SchemeBuffer/" + filename + ".htm";
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an html packet to player with Give Buffs menu info for player and pet, depending on targetType parameter {player, pet}
|
||||
* @param player : The player to make checks on.
|
||||
*/
|
||||
private void showGiveBuffsWindow(L2PcInstance player)
|
||||
{
|
||||
final StringBuilder sb = new StringBuilder(200);
|
||||
|
||||
final Map<String, ArrayList<Integer>> schemes = SchemeBufferTable.getInstance().getPlayerSchemes(player.getObjectId());
|
||||
if ((schemes == null) || schemes.isEmpty())
|
||||
{
|
||||
sb.append("<font color=\"LEVEL\">You haven't defined any scheme.</font>");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Map.Entry<String, ArrayList<Integer>> scheme : schemes.entrySet())
|
||||
{
|
||||
final int cost = getFee(scheme.getValue());
|
||||
sb.append("<font color=\"LEVEL\">" + scheme.getKey() + " [" + scheme.getValue().size() + " / " + player.getStat().getMaxBuffCount() + "]" + ((cost > 0) ? " - cost: " + NumberFormat.getInstance(Locale.ENGLISH).format(cost) : "") + "</font><br1>");
|
||||
sb.append("<a action=\"bypass -h npc_%objectId%_givebuffs " + scheme.getKey() + " " + cost + "\">Use on Me</a> | ");
|
||||
sb.append("<a action=\"bypass -h npc_%objectId%_givebuffs " + scheme.getKey() + " " + cost + " pet\">Use on Pet</a> | ");
|
||||
sb.append("<a action=\"bypass -h npc_%objectId%_editschemes Buffs " + scheme.getKey() + " 1\">Edit</a> | ");
|
||||
sb.append("<a action=\"bypass -h npc_%objectId%_deletescheme " + scheme.getKey() + "\">Delete</a><br>");
|
||||
}
|
||||
}
|
||||
|
||||
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
|
||||
html.setFile(player, getHtmlPath(getId(), 1));
|
||||
html.replace("%schemes%", sb.toString());
|
||||
html.replace("%max_schemes%", Config.BUFFER_MAX_SCHEMES);
|
||||
html.replace("%objectId%", getObjectId());
|
||||
player.sendPacket(html);
|
||||
}
|
||||
|
||||
/**
|
||||
* This sends an html packet to player with Edit Scheme Menu info. This allows player to edit each created scheme (add/delete skills)
|
||||
* @param player : The player to make checks on.
|
||||
* @param groupType : The group of skills to select.
|
||||
* @param schemeName : The scheme to make check.
|
||||
* @param page The page.
|
||||
*/
|
||||
private void showEditSchemeWindow(L2PcInstance player, String groupType, String schemeName, int page)
|
||||
{
|
||||
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
|
||||
final List<Integer> schemeSkills = SchemeBufferTable.getInstance().getScheme(player.getObjectId(), schemeName);
|
||||
|
||||
html.setFile(player, getHtmlPath(getId(), 2));
|
||||
html.replace("%schemename%", schemeName);
|
||||
html.replace("%count%", schemeSkills.size() + " / " + player.getStat().getMaxBuffCount());
|
||||
html.replace("%typesframe%", getTypesFrame(groupType, schemeName));
|
||||
html.replace("%skilllistframe%", getGroupSkillList(player, groupType, schemeName, page));
|
||||
html.replace("%objectId%", getObjectId());
|
||||
player.sendPacket(html);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param player : The player to make checks on.
|
||||
* @param groupType : The group of skills to select.
|
||||
* @param schemeName : The scheme to make check.
|
||||
* @param page The page.
|
||||
* @return a String representing skills available to selection for a given groupType.
|
||||
*/
|
||||
private String getGroupSkillList(L2PcInstance player, String groupType, String schemeName, int page)
|
||||
{
|
||||
// Retrieve the entire skills list based on group type.
|
||||
List<Integer> skills = SchemeBufferTable.getInstance().getSkillsIdsByType(groupType);
|
||||
if (skills.isEmpty())
|
||||
{
|
||||
return "That group doesn't contain any skills.";
|
||||
}
|
||||
|
||||
// Calculate page number.
|
||||
final int max = countPagesNumber(skills.size(), PAGE_LIMIT);
|
||||
if (page > max)
|
||||
{
|
||||
page = max;
|
||||
}
|
||||
|
||||
// Cut skills list up to page number.
|
||||
skills = skills.subList((page - 1) * PAGE_LIMIT, Math.min(page * PAGE_LIMIT, skills.size()));
|
||||
|
||||
final List<Integer> schemeSkills = SchemeBufferTable.getInstance().getScheme(player.getObjectId(), schemeName);
|
||||
final StringBuilder sb = new StringBuilder(skills.size() * 150);
|
||||
|
||||
int row = 0;
|
||||
for (int skillId : skills)
|
||||
{
|
||||
sb.append(((row % 2) == 0 ? "<table width=\"280\" bgcolor=\"000000\"><tr>" : "<table width=\"280\"><tr>"));
|
||||
|
||||
if (skillId < 100)
|
||||
{
|
||||
if (schemeSkills.contains(skillId))
|
||||
{
|
||||
sb.append("<td height=40 width=40><img src=\"icon.skill00" + skillId + "\" width=32 height=32></td><td width=190>" + SkillData.getInstance().getSkill(skillId, 1).getName() + "<br1><font color=\"B09878\">" + SchemeBufferTable.getInstance().getAvailableBuff(skillId).getDescription() + "</font></td><td><button value=\" \" action=\"bypass -h npc_%objectId%_skillunselect " + groupType + " " + schemeName + " " + skillId + " " + page + "\" width=32 height=32 back=\"L2UI_CH3.mapbutton_zoomout2\" fore=\"L2UI_CH3.mapbutton_zoomout1\"></td>");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("<td height=40 width=40><img src=\"icon.skill00" + skillId + "\" width=32 height=32></td><td width=190>" + SkillData.getInstance().getSkill(skillId, 1).getName() + "<br1><font color=\"B09878\">" + SchemeBufferTable.getInstance().getAvailableBuff(skillId).getDescription() + "</font></td><td><button value=\" \" action=\"bypass -h npc_%objectId%_skillselect " + groupType + " " + schemeName + " " + skillId + " " + page + "\" width=32 height=32 back=\"L2UI_CH3.mapbutton_zoomin2\" fore=\"L2UI_CH3.mapbutton_zoomin1\"></td>");
|
||||
}
|
||||
}
|
||||
else if (skillId < 1000)
|
||||
{
|
||||
if (schemeSkills.contains(skillId))
|
||||
{
|
||||
sb.append("<td height=40 width=40><img src=\"icon.skill0" + skillId + "\" width=32 height=32></td><td width=190>" + SkillData.getInstance().getSkill(skillId, 1).getName() + "<br1><font color=\"B09878\">" + SchemeBufferTable.getInstance().getAvailableBuff(skillId).getDescription() + "</font></td><td><button value=\" \" action=\"bypass -h npc_%objectId%_skillunselect " + groupType + " " + schemeName + " " + skillId + " " + page + "\" width=32 height=32 back=\"L2UI_CH3.mapbutton_zoomout2\" fore=\"L2UI_CH3.mapbutton_zoomout1\"></td>");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("<td height=40 width=40><img src=\"icon.skill0" + skillId + "\" width=32 height=32></td><td width=190>" + SkillData.getInstance().getSkill(skillId, 1).getName() + "<br1><font color=\"B09878\">" + SchemeBufferTable.getInstance().getAvailableBuff(skillId).getDescription() + "</font></td><td><button value=\" \" action=\"bypass -h npc_%objectId%_skillselect " + groupType + " " + schemeName + " " + skillId + " " + page + "\" width=32 height=32 back=\"L2UI_CH3.mapbutton_zoomin2\" fore=\"L2UI_CH3.mapbutton_zoomin1\"></td>");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (schemeSkills.contains(skillId))
|
||||
{
|
||||
sb.append("<td height=40 width=40><img src=\"icon.skill" + skillId + "\" width=32 height=32></td><td width=190>" + SkillData.getInstance().getSkill(skillId, 1).getName() + "<br1><font color=\"B09878\">" + SchemeBufferTable.getInstance().getAvailableBuff(skillId).getDescription() + "</font></td><td height=40 width=40><button value=\" \" action=\"bypass -h npc_%objectId%_skillunselect " + groupType + " " + schemeName + " " + skillId + " " + page + "\" width=32 height=32 back=\"L2UI_CH3.mapbutton_zoomout2\" fore=\"L2UI_CH3.mapbutton_zoomout1\"></td>");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("<td height=40 width=40><img src=\"icon.skill" + skillId + "\" width=32 height=32></td><td width=190>" + SkillData.getInstance().getSkill(skillId, 1).getName() + "<br1><font color=\"B09878\">" + SchemeBufferTable.getInstance().getAvailableBuff(skillId).getDescription() + "</font></td><td height=40 width=40><button value=\" \" action=\"bypass -h npc_%objectId%_skillselect " + groupType + " " + schemeName + " " + skillId + " " + page + "\" width=32 height=32 back=\"L2UI_CH3.mapbutton_zoomin2\" fore=\"L2UI_CH3.mapbutton_zoomin1\"></td>");
|
||||
}
|
||||
}
|
||||
|
||||
sb.append("</tr></table><img src=\"L2UI.SquareGray\" width=277 height=1>");
|
||||
row++;
|
||||
}
|
||||
|
||||
// Build page footer.
|
||||
sb.append("<br><img src=\"L2UI.SquareGray\" width=277 height=1><table width=\"100%\" bgcolor=000000><tr>");
|
||||
|
||||
if (page > 1)
|
||||
{
|
||||
sb.append("<td align=left width=70><a action=\"bypass -h npc_" + getObjectId() + "_editschemes " + groupType + " " + schemeName + " " + (page - 1) + "\">Previous</a></td>");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("<td align=left width=70>Previous</td>");
|
||||
}
|
||||
|
||||
sb.append("<td align=center width=100>Page " + page + "</td>");
|
||||
|
||||
if (page < max)
|
||||
{
|
||||
sb.append("<td align=right width=70><a action=\"bypass -h npc_" + getObjectId() + "_editschemes " + groupType + " " + schemeName + " " + (page + 1) + "\">Next</a></td>");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("<td align=right width=70>Next</td>");
|
||||
}
|
||||
|
||||
sb.append("</tr></table><img src=\"L2UI.SquareGray\" width=277 height=1>");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param groupType : The group of skills to select.
|
||||
* @param schemeName : The scheme to make check.
|
||||
* @return a string representing all groupTypes available. The group currently on selection isn't linkable.
|
||||
*/
|
||||
private static String getTypesFrame(String groupType, String schemeName)
|
||||
{
|
||||
final StringBuilder sb = new StringBuilder(500);
|
||||
sb.append("<table>");
|
||||
|
||||
int count = 0;
|
||||
for (String type : SchemeBufferTable.getInstance().getSkillTypes())
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
sb.append("<tr>");
|
||||
}
|
||||
|
||||
if (groupType.equalsIgnoreCase(type))
|
||||
{
|
||||
sb.append("<td width=65>" + type + "</td>");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("<td width=65><a action=\"bypass -h npc_%objectId%_editschemes " + type + " " + schemeName + " 1\">" + type + "</a></td>");
|
||||
}
|
||||
|
||||
count++;
|
||||
if (count == 4)
|
||||
{
|
||||
sb.append("</tr>");
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sb.toString().endsWith("</tr>"))
|
||||
{
|
||||
sb.append("</tr>");
|
||||
}
|
||||
|
||||
sb.append("</table>");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list : A list of skill ids.
|
||||
* @return a global fee for all skills contained in list.
|
||||
*/
|
||||
private static int getFee(ArrayList<Integer> list)
|
||||
{
|
||||
if (Config.BUFFER_STATIC_BUFF_COST > 0)
|
||||
{
|
||||
return list.size() * Config.BUFFER_STATIC_BUFF_COST;
|
||||
}
|
||||
|
||||
int fee = 0;
|
||||
for (int sk : list)
|
||||
{
|
||||
fee += SchemeBufferTable.getInstance().getAvailableBuff(sk).getValue();
|
||||
}
|
||||
|
||||
return fee;
|
||||
}
|
||||
|
||||
private static int countPagesNumber(int objectsSize, int pageSize)
|
||||
{
|
||||
return (objectsSize / pageSize) + ((objectsSize % pageSize) == 0 ? 0 : 1);
|
||||
}
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
package com.l2jmobius.gameserver.model.holders;
|
||||
|
||||
/**
|
||||
* A container used for schemes buffer.
|
||||
*/
|
||||
public final class BuffSkillHolder extends IntIntHolder
|
||||
{
|
||||
private final String _type;
|
||||
private final String _description;
|
||||
|
||||
public BuffSkillHolder(int id, int price, String type, String description)
|
||||
{
|
||||
super(id, price);
|
||||
|
||||
_type = type;
|
||||
_description = description;
|
||||
}
|
||||
|
||||
public final String getType()
|
||||
{
|
||||
return _type;
|
||||
}
|
||||
|
||||
public final String getDescription()
|
||||
{
|
||||
return _description;
|
||||
}
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
package com.l2jmobius.gameserver.model.holders;
|
||||
|
||||
import com.l2jmobius.gameserver.data.xml.impl.SkillData;
|
||||
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||
|
||||
/**
|
||||
* A generic int/int container.
|
||||
*/
|
||||
public class IntIntHolder
|
||||
{
|
||||
private int _id;
|
||||
private int _value;
|
||||
|
||||
public IntIntHolder(int id, int value)
|
||||
{
|
||||
_id = id;
|
||||
_value = value;
|
||||
}
|
||||
|
||||
public int getId()
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
|
||||
public int getValue()
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
public void setId(int id)
|
||||
{
|
||||
_id = id;
|
||||
}
|
||||
|
||||
public void setValue(int value)
|
||||
{
|
||||
_value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the L2Skill associated to the id/value.
|
||||
*/
|
||||
public final Skill getSkill()
|
||||
{
|
||||
return SkillData.getInstance().getSkill(_id, _value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getClass().getSimpleName() + ": Id: " + _id + ", Value: " + _value;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user