Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

[RELEASE] OdinMS BASE PvP

Status
Not open for further replies.
Banned
Banned
Joined
Sep 25, 2006
Messages
295
Reaction score
1
This is my base code for pvp in OdinMS. There's still a lot missing but it works fine. I'll be posting updates here from now on. Please for gods sake follow the directions thoroughly, if you make an obvious mistake while implementing this I will not give support. If you have errors about missing symbols please post them as soon as possible and I'll get the correct imports added to the setup.

In your database run these queries.
Code:
ALTER TABLE `characters` ADD COLUMN `pvpkills` int(11) NOT NULL DEFAULT '0' AFTER `messengerposition`;
Code:
ALTER TABLE `characters` ADD COLUMN `pvpdeaths` int(11) NOT NULL DEFAULT '0' AFTER `pvpkills`;

Make a new net.sf.odinms.net.channel.pvp java package.
Make a new MaplePvp.java class file inside the package.
Copy and paste this into MaplePvp.java.
Code:
/*
	This file is part of the OdinMS Maple Story Server
    Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc> 
                       Matthias Butz <matze@odinms.de>
                       Jan Christian Meyer <vimes@odinms.de>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License version 3
    as published by the Free Software Foundation. You may not use, modify
    or distribute this program under any other version of the
    GNU Affero General Public License.

    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 Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package net.sf.odinms.net.channel.pvp;

import java.util.Collections;
import java.util.ArrayList;
import java.util.List;

import net.sf.odinms.client.MapleCharacter;
import net.sf.odinms.client.MapleBuffStat;
import net.sf.odinms.client.MapleStat;
import net.sf.odinms.client.MapleJob;
import net.sf.odinms.net.world.guild.MapleGuild;
import net.sf.odinms.net.channel.handler.AbstractDealDamageHandler;
import net.sf.odinms.server.life.MapleMonster;
import net.sf.odinms.server.life.MapleLifeFactory;
import net.sf.odinms.server.maps.MapleMap;
import net.sf.odinms.tools.MaplePacketCreator;
import net.sf.odinms.tools.Pair;

public class MaplePvp {
        private static int pvpDamage;
        private static int maxDis;
        private static int maxHeight;
        private static boolean isAoe = false;
        public static boolean isLeft = false;
        public static boolean isRight = false;

        private static boolean isMeleeAttack(AbstractDealDamageHandler.AttackInfo attack) {
                switch(attack.skill) {
                        case 1001004:    //Power Strike
                        case 1001005:    //Slash Blast
                        case 4001334:    //Double Stab
                        case 4201005:    //Savage Blow
                        case 1111004:    //Panic: Axe
                        case 1111003:    //Panic: Sword
                        case 1311004:    //Dragon Fury: Pole Arm
                        case 1311003:    //Dragon Fury: Spear
                        case 1311002:    //Pole Arm Crusher
                        case 1311005:    //Sacrifice
                        case 1311001:    //Spear Crusher
                        case 1121008:    //Brandish
                        case 1221009:    //Blast
                        case 1121006:    //Rush
                        case 1221007:    //Rush
                        case 1321003:    //Rush
                        case 4221001:    //Assassinate
                        return true;
                }
                return false;
        }

        private static boolean isRangeAttack(AbstractDealDamageHandler.AttackInfo attack) {
                switch(attack.skill) {
                        case 2001004:    //Energy Bolt
                        case 2001005:    //Magic Claw
                        case 3001004:    //Arrow Blow
                        case 3001005:    //Double Shot
                        case 4001344:    //Lucky Seven
                        case 2101004:    //Fire Arrow
                        case 2101005:    //Poison Brace
                        case 2201004:    //Cold Beam
                        case 2301005:    //Holy Arrow
                        case 4101005:    //Drain
                        case 2211002:    //Ice Strike
                        case 2211003:    //Thunder Spear
                        case 3111006:    //Strafe
                        case 3211006:    //Strafe
                        case 4111005:    //Avenger
                        case 4211002:    //Assaulter
                        case 2121003:    //Fire Demon
                        case 2221006:    //Chain Lightning
                        case 2221003:    //Ice Demon
                        case 2111006:	 //Element Composition F/P
                        case 2211006:	 //Element Composition I/L
                        case 2321007:    //Angel's Ray
                        case 3121003:    //Dragon Pulse
                        case 3121004:    //Hurricane
                        case 3221003:    //Dragon Pulse
                        case 3221001:    //Piercing
                        case 3221007:    //Sniping
                        case 4121003:    //Showdown taunt
                        case 4121007:    //Triple Throw
                        case 4221007:    //Boomerang Step
                        case 4221003:    //Showdown taunt
                        case 4111004:    //Shadow Meso
                        return true;
                }
                return false;
        }

        private static boolean isAoeAttack(AbstractDealDamageHandler.AttackInfo attack) {
                switch(attack.skill) {
                        case 2201005:    //Thunderbolt
                        case 3101005:    //Arrow Bomb : Bow
                        case 3201005:    //Iron Arrow : Crossbow
                        case 1111006:    //Coma: Axe
                        case 1111005:    //Coma: Sword
                        case 1211002:    //Charged Blow
                        case 1311006:    //Dragon Roar
                        case 2111002:    //Explosion
                        case 2111003:    //Poison Mist
                        case 2311004:    //Shining Ray
                        case 3111004:    //Arrow Rain
                        case 3111003:    //Inferno
                        case 3211004:    //Arrow Eruption
                        case 3211003:    //Blizzard (Sniper)
                        case 4211004:    //Band of Thieves
                        case 1221011:    //Sanctuary Skill
                        case 2121001:    //Big Bang
                        case 2121007:    //Meteo
                        case 2121006:    //Paralyze
                        case 2221001:    //Big Bang
                        case 2221007:    //Blizzard
                        case 2321008:    //Genesis
                        case 2321001:    //Big Bang
                        case 4121004:    //Ninja Ambush
                        case 4121008:    //Ninja Storm knockback
                        case 4221004:    //Ninja Ambush
                        return true;
                }
                return false;
        }

        private static void getDirection(AbstractDealDamageHandler.AttackInfo attack) {
                if (isAoe) {
                        isRight = true;
                        isLeft = true;
                } else if (attack.direction <= 0 && attack.stance <= 0) {
                        isRight = false;
                        isLeft = true;
                } else {
                        isRight = true;
                        isLeft = false;
                }
        }

        private static void DamageBalancer(AbstractDealDamageHandler.AttackInfo attack) {
                if (attack.skill == 0) {
                        pvpDamage = 100;
                        maxDis = 130;
                        maxHeight = 35;
                } else if (isMeleeAttack(attack)) {
                        maxDis = 130;
                        maxHeight = 45;
                        isAoe = false;
                        if (attack.skill == 4201005) {
                                pvpDamage = (int) (Math.floor(Math.random() * (75 - 5) + 5));
                        } else if (attack.skill == 1121008) {
                                pvpDamage = (int) (Math.floor(Math.random() * (320 - 180) + 180));
                                maxHeight = 50;
                        } else if (attack.skill == 4221001) {
                                pvpDamage = (int) (Math.floor(Math.random() * (200 - 150) + 150));
                        } else if (attack.skill == 1121006 || attack.skill == 1221007 || attack.skill == 1321003) {
                                pvpDamage = (int) (Math.floor(Math.random() * (200 - 80) + 80));
                        } else {
                                pvpDamage = (int) (Math.floor(Math.random() * (600 - 250) + 250));
                        }
                } else if (isRangeAttack(attack)) {
                        maxDis = 300;
                        maxHeight = 40;
                        isAoe = false;
                        if (attack.skill == 4201005) {
                                pvpDamage = (int) (Math.floor(Math.random() * (75 - 5) + 5));
                        } else if (attack.skill == 4121007) {
                                pvpDamage = (int) (Math.floor(Math.random() * (60 - 15) + 15));
                        } else if (attack.skill == 4001344 || attack.skill == 2001005) {
                                pvpDamage = (int) (Math.floor(Math.random() * (195 - 90) + 90));
                        } else if (attack.skill == 4221007) {
                                pvpDamage = (int) (Math.floor(Math.random() * (350 - 180) + 180));
                        } else if (attack.skill == 3121004 || attack.skill == 3111006 || attack.skill == 3211006) {
                                maxDis = 450;
                                pvpDamage = (int) (Math.floor(Math.random() * (50 - 20) + 20));
                        } else if (attack.skill == 2121003 || attack.skill == 2221003) {
                                pvpDamage = (int) (Math.floor(Math.random() * (600 - 300) + 300));
                        } else {
                                pvpDamage = (int) (Math.floor(Math.random() * (400 - 250) + 250));
                        }
                } else if (isAoeAttack(attack)) {
                        maxDis = 350;
                        maxHeight = 350;
                        isAoe = true;
                        if (attack.skill == 2121001 || attack.skill == 2221001 || attack.skill == 2321001 || attack.skill == 2121006) {
                                maxDis = 175;
                                maxHeight = 175;
                                pvpDamage = (int) (Math.floor(Math.random() * (350 - 180) + 180));
                        } else {
                                pvpDamage = (int) (Math.floor(Math.random() * (700 - 300) + 300));
                        }
                }
        }

        private static void monsterBomb(MapleCharacter player, MapleCharacter attackedPlayers, MapleMap map, AbstractDealDamageHandler.AttackInfo attack) {
                //level balances
                if (attackedPlayers.getLevel() > player.getLevel() + 25) {
                        pvpDamage *= 1.35;
                } else if (attackedPlayers.getLevel() < player.getLevel() - 25) {
                        pvpDamage /= 1.35;
                } else if (attackedPlayers.getLevel() > player.getLevel() + 100) {
                        pvpDamage *= 1.50;
                } else if (attackedPlayers.getLevel() < player.getLevel() - 100) {
                        pvpDamage /= 1.50;
                }
                //class balances
                if (player.getJob().equals(MapleJob.MAGICIAN)) {
                        pvpDamage *= 1.20;
                }

                //buff modifiers
		Integer mguard = attackedPlayers.getBuffedValue(MapleBuffStat.MAGIC_GUARD);
		Integer mesoguard = attackedPlayers.getBuffedValue(MapleBuffStat.MESOGUARD);
		if (mguard != null) {
			int mploss = (int) (pvpDamage / .5);
                        pvpDamage *= .70;
			if (mploss > attackedPlayers.getMp()) {
                                pvpDamage /= .70;
				attackedPlayers.cancelBuffStats(MapleBuffStat.MAGIC_GUARD);
			} else {
                                attackedPlayers.setMp(attackedPlayers.getMp() - mploss);
                                attackedPlayers.updateSingleStat(MapleStat.MP, attackedPlayers.getMp());
                        }
		} else if (mesoguard != null) { 
			int mesoloss = (int) (pvpDamage * .75);
                        pvpDamage *= .75;
			if(mesoloss > attackedPlayers.getMeso()) {
                                        pvpDamage /= .75;
					attackedPlayers.cancelBuffStats(MapleBuffStat.MESOGUARD);
			} else {
					attackedPlayers.gainMeso(-mesoloss, false);
			}
                }

                //set up us teh bonmb
                //training thingy = 9409000
                MapleMonster pvpMob = MapleLifeFactory.getMonster(9400711);
                map.spawnMonsterOnGroundBelow(pvpMob, attackedPlayers.getPosition());
                for (int attacks = 0; attacks < attack.numDamage; attacks++) {
                        map.broadcastMessage(MaplePacketCreator.damagePlayer(attack.numDamage, pvpMob.getId(), attackedPlayers.getId(), pvpDamage));
                        attackedPlayers.addHP(-pvpDamage);
                }
                int attackedDamage = pvpDamage * attack.numDamage;
                attackedPlayers.getClient().getSession().write(MaplePacketCreator.serverNotice(5, player.getName() + " has hit you for " + attackedDamage + " damage!"));
                map.killMonster(pvpMob, player, false);

                //rewards
                if (attackedPlayers.getHp() <= 0 && !attackedPlayers.isAlive()) {
                        int expReward = attackedPlayers.getLevel() * 100;
                        int gpReward = (int) (Math.floor(Math.random() * (200 - 50) + 50));
                        if (player.getPvpKills() * .25 >= player.getPvpDeaths()) {
                                expReward *= 20;
                        }
                        player.gainExp(expReward, true, false);
                        if (player.getGuildId() != 0 && player.getGuildId() != attackedPlayers.getGuildId()) {
                                try {
                                        MapleGuild guild = player.getClient().getChannelServer().getWorldInterface().getGuild(player.getGuildId(), null);
                                        guild.gainGP(gpReward);
                                } catch (Exception e) {}
                        }
                        player.gainPvpKill();
                        player.getClient().getSession().write(MaplePacketCreator.serverNotice(6, "You've killed " + attackedPlayers.getName() + "!! You've gained a pvp kill!"));
                        attackedPlayers.gainPvpDeath();
                        attackedPlayers.getClient().getSession().write(MaplePacketCreator.serverNotice(6, player.getName() + " has killed you!"));
                }
        }

        public static void doPvP(MapleCharacter player, MapleMap map, AbstractDealDamageHandler.AttackInfo attack) {
                DamageBalancer(attack);
                getDirection(attack);
                for (MapleCharacter attackedPlayers : player.getMap().getNearestPvpChar(player.getPosition(), maxDis, maxHeight, player.getMap().getCharacters())) {
                        if (attackedPlayers.isAlive() && (player.getParty() == null || player.getParty() != attackedPlayers.getParty())) {
                                monsterBomb(player, attackedPlayers, map, attack);
                        }
                }
        }
}

In AbstractDealDamageHandler.java

Add import
Code:
import net.sf.odinms.net.channel.pvp.MaplePvp;

Change
Code:
protected static class AttackInfo {
to
Code:
public static class AttackInfo {

Add
Code:
        private int PVP_MAP = themapidyouwantforpvp;
above
Code:
public static class AttackInfo {

Add
Code:
                //pvp monster bombscase
                if (attack.skill != 2301002 && attack.skill != 4201004 && attack.skill != 1111008 && player.getMapId() == PVP_MAP) {//checks
                        MaplePvp.doPvP(player, map, attack);
                }
                //end pvp monster bombs
Under
Code:
        MapleMap map = player.getMap();

In MapleMap.java

Add import
Code:
import net.sf.odinms.net.channel.pvp.MaplePvp;

Add
Code:
        public Collection<MapleCharacter> getNearestPvpChar(Point attacker, double maxRange, double maxHeight, Collection<MapleCharacter> chr) {
                Collection<MapleCharacter> character = new LinkedList<MapleCharacter>();
                for (MapleCharacter a : characters) {
                        if (chr.contains(a.getClient().getPlayer())) {
                                Point attackedPlayer = a.getPosition();
                                MaplePortal Port = a.getMap().findClosestSpawnpoint(a.getPosition());
                                Point nearestPort = Port.getPosition();
                                double safeDis = attackedPlayer.distance(nearestPort);
                                double distanceX = attacker.distance(attackedPlayer.getX(), attackedPlayer.getY());
                                if(MaplePvp.isLeft) {
                                        if (attacker.x > attackedPlayer.x && distanceX < maxRange && distanceX > 2 &&
                                                attackedPlayer.y >= attacker.y - maxHeight && attackedPlayer.y <= attacker.y + maxHeight && safeDis > 2) {
                                                character.add(a);
                                        }
                                }
                                if(MaplePvp.isRight) {
                                        if (attacker.x < attackedPlayer.x && distanceX < maxRange && distanceX > 2 &&
                                                attackedPlayer.y >= attacker.y - maxHeight && attackedPlayer.y <= attacker.y + maxHeight && safeDis > 2) {
                                                character.add(a);
                                        }
                                }
                        }
                }
                return character;
        }

In MapleCharacter.java
Add
Code:
        //pvp
        private int pvpkills;
        private int pvpdeaths;
above
Code:
	private int str, dex, luk, int_;

Add
Code:
                //pvp
                ret.pvpdeaths = rs.getInt("pvpdeaths");
                ret.pvpkills = rs.getInt("pvpkills");
under
Code:
		ret.level = rs.getInt("level");

Add
Code:
                ret.pvpdeaths = 0;
                ret.pvpkills = 0;
above
Code:
		ret.accountid = client.getAccID();

Replace the if(update){ code block with this.
Code:
			if (update) {
				ps = con.prepareStatement("UPDATE characters "
					+ "SET level = ?, fame = ?, str = ?, dex = ?, luk = ?, `int` = ?, "
					+ "exp = ?, hp = ?, mp = ?, maxhp = ?, maxmp = ?, sp = ?, ap = ?, "
					+ "gm = ?, skincolor = ?, gender = ?, job = ?, hair = ?, face = ?, map = ?, "
					+ "meso = ?, hpApUsed = ?, mpApUsed = ?, spawnpoint = ?, party = ?, buddyCapacity = ?, messengerid = ?, messengerposition = ?, pvpkills = ?, pvpdeaths = ? WHERE id = ?");
			} else {
                            //31 inserts
				ps = con
					.prepareStatement("INSERT INTO characters ("
						+ "level, fame, str, dex, luk, `int`, exp, hp, mp, "
						+ "maxhp, maxmp, sp, ap, gm, skincolor, gender, job, hair, face, map, meso, hpApUsed, mpApUsed, spawnpoint, party, buddyCapacity, messengerid, messengerposition, pvpkills, pvpdeaths, accountid, name, world"
						+ ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
			}

Replace
Code:
			if (update) {
				ps.setInt(29, id);
			} else {
				ps.setInt(29, accountid);
                                ps.setString(30, name);
				ps.setInt(31, world); // TODO store world somewhere ;)
			}
With
Code:
                        ps.setInt(29, pvpkills);
                        ps.setInt(30, pvpdeaths);

			if (update) {
				ps.setInt(31, id);
			} else {
				ps.setInt(31, accountid);
                                ps.setString(32, name);
				ps.setInt(33, world); // TODO store world somewhere ;)
			}

Add
Code:
        public int getPvpKills() {
                return pvpkills;
        }
        
        public int getPvpDeaths() {
                return pvpdeaths;
        }
above
Code:
	public int getHp() {
		return hp;
	}

Add
Code:
        public void setPvpDeaths(int amount) {
                this.pvpdeaths = amount;
        }

        public void setPvpKills(int amount) {
                this.pvpkills = amount;
        }
        public void gainPvpDeath() {
                this.pvpdeaths += 1;
        }

        public void gainPvpKill() {
                this.pvpkills += 1;
        }
above
Code:
	public void setSkinColor(MapleSkinColor skinColor) {
		this.skinColor = skinColor;
	}
 
Last edited:
Elite Diviner
Joined
May 25, 2008
Messages
454
Reaction score
0
Re: [RELEASE] OdinMS BASE PvP *wut

thx..I WILL TRY IT!! FIRST TO POST ^^
 
Newbie Spellweaver
Joined
Feb 15, 2008
Messages
96
Reaction score
0
Re: [RELEASE] OdinMS BASE PvP *wut

if this works you are a god
 
Banned
Banned
Joined
Sep 25, 2006
Messages
295
Reaction score
1
Re: [RELEASE] OdinMS BASE PvP *Still Adding

Not done adding yet, gotta write the rest for pvpkills/deaths ee;
 
Experienced Elementalist
Joined
Jun 15, 2008
Messages
299
Reaction score
0
Re: [RELEASE] OdinMS BASE PvP *Still Adding

nice cant wait!!
 
Newbie Spellweaver
Joined
Feb 15, 2008
Messages
96
Reaction score
0
Re: [RELEASE] OdinMS BASE PvP *Still Adding

Not done adding yet, gotta write the rest for pvpkills/deaths ee;

wait so ATM skills dont work on ppl and they cant die lol?
 
Newbie Spellweaver
Joined
Jun 28, 2008
Messages
48
Reaction score
0
Re: [RELEASE] OdinMS BASE PvP *Still Adding

We will be rootn' for ya.
 
Newbie Spellweaver
Joined
Apr 4, 2008
Messages
96
Reaction score
0
Re: [RELEASE] OdinMS BASE PvP *Still Adding

100% Support U!!
 
Skilled Illusionist
Joined
May 22, 2008
Messages
380
Reaction score
0
Re: [RELEASE] OdinMS BASE PvP *Still Adding

Nice ~~ i will be waiting for it ~
 
LeviathanStory
Joined
Apr 21, 2007
Messages
251
Reaction score
0
Re: [RELEASE] OdinMS BASE PvP *Still Adding

Awesome! But shouldnt this be in Dev?
 
Banned
Banned
Joined
Sep 25, 2006
Messages
295
Reaction score
1
Re: [RELEASE] OdinMS BASE PvP *Still Adding

Completed, you can now apply the changes. HF
 
LeviathanStory
Joined
Apr 21, 2007
Messages
251
Reaction score
0
Make a new net.sf.odinms.net.channel.pvp java package.
Make a new MaplePvp.java class file inside the package.
Copy and paste this into MaplePvp.java
Care to elaborate? And YAY!
 
Junior Spellweaver
Joined
Jun 24, 2008
Messages
151
Reaction score
0
Make a new net.sf.odinms.net.channel.pvp java package.
Make a new MaplePvp.java class file inside the package.
im kinda new new at this stuff but how do we make this? and after we make it wea do i put it?
 
Status
Not open for further replies.
Back
Top