Chronicle 4 branch.
This commit is contained in:
0
L2J_Mobius_C4/dist/game/data/scripts/ai/__init__.py
vendored
Normal file
0
L2J_Mobius_C4/dist/game/data/scripts/ai/__init__.py
vendored
Normal file
0
L2J_Mobius_C4/dist/game/data/scripts/ai/group_template/__init__.py
vendored
Normal file
0
L2J_Mobius_C4/dist/game/data/scripts/ai/group_template/__init__.py
vendored
Normal file
100
L2J_Mobius_C4/dist/game/data/scripts/ai/group_template/chests.py
vendored
Normal file
100
L2J_Mobius_C4/dist/game/data/scripts/ai/group_template/chests.py
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
# # # # # # # # # # #
|
||||
# Chest AI implementation.
|
||||
# Written by Fulminus
|
||||
# # # # # # # # # # #
|
||||
import sys
|
||||
from com.l2jmobius.gameserver.ai import CtrlIntention
|
||||
from com.l2jmobius.gameserver.model.quest import QuestState
|
||||
from com.l2jmobius.gameserver.model.quest.jython import QuestJython as JQuest
|
||||
from com.l2jmobius.util import Rnd;
|
||||
|
||||
SKILL_DELUXE_KEY = 2229
|
||||
|
||||
#Base chance for BOX to be opened
|
||||
BASE_CHANCE = 100
|
||||
|
||||
# Percent to decrease base chance when grade of DELUXE key not match
|
||||
LEVEL_DECREASE = 40
|
||||
|
||||
# Chance for a chest to actually be a BOX (as opposed to being a mimic).
|
||||
IS_BOX = 40
|
||||
|
||||
class chests(JQuest) :
|
||||
|
||||
# init function. Add in here variables that you'd like to be inherited by subclasses (if any)
|
||||
def __init__(self,id,name,descr):
|
||||
# firstly, don't forget to call the parent constructor to prepare the event triggering
|
||||
# mechanisms etc.
|
||||
JQuest.__init__(self,id,name,descr)
|
||||
|
||||
self.chests = [13100,13101,13102,13103,13104,13105,13106,13107,13108,13109, \
|
||||
13110,13111,13112,13113,13114,13115,13116,13117,13118,13119, \
|
||||
13120,13121,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810, \
|
||||
1671,1694,1717,1740,1763,1786,13213,13215,13217,13219,13221,13223, \
|
||||
1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822]
|
||||
|
||||
for i in self.chests :
|
||||
self.addSkillSeeId(i)
|
||||
self.addAttackId(i)
|
||||
|
||||
def onSkillSee (self,npc,player,skill,targets,isPet):
|
||||
if npc not in targets :
|
||||
return
|
||||
npcId = npc.getNpcId()
|
||||
skillId = skill.getId()
|
||||
skillLevel= skill.getLevel()
|
||||
# check if the npc and skills used are valid for this script. Exit if invalid.
|
||||
if npcId not in self.chests :
|
||||
return
|
||||
# if this has already been interacted, no further ai decisions are needed
|
||||
# if it's the first interaction, check if this is a box or mimic
|
||||
if not npc.isInteracted() :
|
||||
npc.setInteracted()
|
||||
if Rnd.get(100) < IS_BOX :
|
||||
# if it's a box, either it will be successfully openned by a proper key, or instantly disappear
|
||||
if skillId == SKILL_DELUXE_KEY :
|
||||
# check the chance to open the box
|
||||
keyLevelNeeded = int(npc.getLevel()/10)
|
||||
levelDiff = keyLevelNeeded - skillLevel
|
||||
if levelDiff < 0 :
|
||||
levelDiff = levelDiff * (-1)
|
||||
chance = BASE_CHANCE - levelDiff * LEVEL_DECREASE
|
||||
# success, pretend-death with rewards: npc.reduceCurrentHp(99999999, player)
|
||||
if Rnd.get(100) < chance :
|
||||
npc.setMustRewardExpSp(False)
|
||||
npc.setSpecialDrop();
|
||||
npc.reduceCurrentHp(99999999, player)
|
||||
return
|
||||
# used a skill other than chest-key, or used a chest-key but failed to open: disappear with no rewards
|
||||
npc.onDecay()
|
||||
else :
|
||||
attacker = player
|
||||
if npc.getAttackByList().contains(player.getPet()):
|
||||
attacker = player.getPet()
|
||||
npc.setRunning()
|
||||
npc.addDamageHate(attacker,0,999)
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, attacker)
|
||||
return
|
||||
|
||||
def onAttack(self,npc,player,damage,isPet) :
|
||||
npcId = npc.getNpcId()
|
||||
# check if the npc and skills used are valid for this script. Exit if invalid.
|
||||
if npcId not in self.chests :
|
||||
return
|
||||
# if this was a mimic, set the target, start the skills and become agro
|
||||
if not npc.isInteracted() :
|
||||
npc.setInteracted()
|
||||
if Rnd.get(100) < IS_BOX :
|
||||
npc.onDecay()
|
||||
else : # if this weren't a box, upon interaction start the mimic behaviors...
|
||||
# todo: perhaps a self-buff (skill id 4245) with random chance goes here?
|
||||
attacker = player
|
||||
if isPet:
|
||||
attacker = player.getPet()
|
||||
npc.setRunning()
|
||||
npc.addDamageHate(attacker,0,(damage*100)/(npc.getLevel()+7))
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, attacker)
|
||||
return
|
||||
|
||||
# now call the constructor (starts up the ai)
|
||||
QUEST = chests(-1,"chests","ai")
|
32
L2J_Mobius_C4/dist/game/data/scripts/ai/group_template/fairy_trees.py
vendored
Normal file
32
L2J_Mobius_C4/dist/game/data/scripts/ai/group_template/fairy_trees.py
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
import sys
|
||||
from com.l2jmobius.gameserver.ai import CtrlIntention
|
||||
from com.l2jmobius.gameserver.datatables import SkillTable
|
||||
from com.l2jmobius.gameserver.model.quest import Quest as JQuest
|
||||
from com.l2jmobius.util import Rnd
|
||||
|
||||
class trees(JQuest) :
|
||||
|
||||
def __init__(self,id,name,descr):
|
||||
JQuest.__init__(self,id,name,descr)
|
||||
|
||||
def onKill (self,npc,player,isPet):
|
||||
npcId = npc.getNpcId()
|
||||
if npcId in range(5185,5189) :
|
||||
for x in xrange(20):
|
||||
newNpc = self.addSpawn(5189,npc.getX(),npc.getY(),npc.getZ(),0,False,30000)
|
||||
killer = player
|
||||
if isPet :
|
||||
killer = player.getPet()
|
||||
newNpc.setRunning()
|
||||
newNpc.addDamageHate(killer,0,999)
|
||||
newNpc.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, killer)
|
||||
if Rnd.get(2) :
|
||||
skill = SkillTable.getInstance().getInfo(4243,1)
|
||||
if skill != None and killer:
|
||||
skill.getEffects(newNpc, killer)
|
||||
return
|
||||
|
||||
QUEST = trees(-1,"fairy_trees","ai")
|
||||
|
||||
for i in range(5185,5189):
|
||||
QUEST.addKillId(i)
|
229
L2J_Mobius_C4/dist/game/data/scripts/ai/group_template/feedable_beasts.py
vendored
Normal file
229
L2J_Mobius_C4/dist/game/data/scripts/ai/group_template/feedable_beasts.py
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
# Growth-capable mobs: Polymorphing upon successful feeding.
|
||||
# Written by Fulminus
|
||||
# # # # # # # # # # #
|
||||
import sys
|
||||
from com.l2jmobius.gameserver.ai import CtrlIntention
|
||||
from com.l2jmobius.gameserver.datatables import NpcTable
|
||||
from com.l2jmobius.gameserver.idfactory import IdFactory
|
||||
from com.l2jmobius.gameserver.model.actor.instance import L2TamedBeastInstance
|
||||
from com.l2jmobius.gameserver.model.quest.jython import QuestJython as JQuest
|
||||
from com.l2jmobius.gameserver.network.serverpackets import CreatureSay
|
||||
from com.l2jmobius.gameserver.network.serverpackets import SocialAction
|
||||
from com.l2jmobius.util import Rnd;
|
||||
|
||||
GOLDEN_SPICE = 6643
|
||||
CRYSTAL_SPICE = 6644
|
||||
SKILL_GOLDEN_SPICE = 2188
|
||||
SKILL_CRYSTAL_SPICE = 2189
|
||||
foodSkill = {GOLDEN_SPICE:SKILL_GOLDEN_SPICE, CRYSTAL_SPICE:SKILL_CRYSTAL_SPICE}
|
||||
|
||||
class feedable_beasts(JQuest) :
|
||||
|
||||
# init function. Add in here variables that you'd like to be inherited by subclasses (if any)
|
||||
def __init__(self,id,name,descr):
|
||||
# firstly, don't forget to call the parent constructor to prepare the event triggering
|
||||
# mechanisms etc.
|
||||
JQuest.__init__(self,id,name,descr)
|
||||
# DEFINE MEMBER VARIABLES FOR THIS AI
|
||||
# all mobs that can eat...
|
||||
self.tamedBeasts = range(12783,12789)
|
||||
self.feedableBeasts = range(1451,1508)+ self.tamedBeasts
|
||||
# all mobs that grow by eating
|
||||
# mobId: current_growth_level, {food: [list of possible mobs[possible sublist of tamed pets]]}, chance of growth
|
||||
self.growthCapableMobs = {
|
||||
# Alpen Kookabura
|
||||
1451: [0,{GOLDEN_SPICE:[1452,1453, 1454, 1455],CRYSTAL_SPICE:[1456,1457, 1458, 1459]},100],
|
||||
1452: [1,{GOLDEN_SPICE:[1460,1462],CRYSTAL_SPICE:[]},40],
|
||||
1453: [1,{GOLDEN_SPICE:[1461,1463],CRYSTAL_SPICE:[]},40],
|
||||
1454: [1,{GOLDEN_SPICE:[1460,1462],CRYSTAL_SPICE:[]},40],
|
||||
1455: [1,{GOLDEN_SPICE:[1461,1463],CRYSTAL_SPICE:[]},40],
|
||||
1456: [1,{GOLDEN_SPICE:[],CRYSTAL_SPICE:[1464,1466]},40],
|
||||
1457: [1,{GOLDEN_SPICE:[],CRYSTAL_SPICE:[1465,1467]},40],
|
||||
1458: [1,{GOLDEN_SPICE:[],CRYSTAL_SPICE:[1464,1466]},40],
|
||||
1459: [1,{GOLDEN_SPICE:[],CRYSTAL_SPICE:[1465,1467]},40],
|
||||
1460: [2,{GOLDEN_SPICE:[[1468,1469],[12783,12784]],CRYSTAL_SPICE:[]},25],
|
||||
1461: [2,{GOLDEN_SPICE:[[1468,1469],[12783,12784]],CRYSTAL_SPICE:[]},25],
|
||||
1462: [2,{GOLDEN_SPICE:[[1468,1469],[12783,12784]],CRYSTAL_SPICE:[]},25],
|
||||
1463: [2,{GOLDEN_SPICE:[[1468,1469],[12783,12784]],CRYSTAL_SPICE:[]},25],
|
||||
1464: [2,{GOLDEN_SPICE:[],CRYSTAL_SPICE:[[1468,1469],[12783,12784]]},25],
|
||||
1465: [2,{GOLDEN_SPICE:[],CRYSTAL_SPICE:[[1468,1469],[12783,12784]]},25],
|
||||
1466: [2,{GOLDEN_SPICE:[],CRYSTAL_SPICE:[[1468,1469],[12783,12784]]},25],
|
||||
1467: [2,{GOLDEN_SPICE:[],CRYSTAL_SPICE:[[1468,1469],[12783,12784]]},25],
|
||||
# Alpen Buffalo
|
||||
1470: [0,{GOLDEN_SPICE:[1471,1472, 1473, 1474],CRYSTAL_SPICE:[1475,1476, 1477, 1478]},100],
|
||||
1471: [1,{GOLDEN_SPICE:[1479,1481],CRYSTAL_SPICE:[]},40],
|
||||
1472: [1,{GOLDEN_SPICE:[1481,1482],CRYSTAL_SPICE:[]},40],
|
||||
1473: [1,{GOLDEN_SPICE:[1479,1481],CRYSTAL_SPICE:[]},40],
|
||||
1474: [1,{GOLDEN_SPICE:[1480,1482],CRYSTAL_SPICE:[]},40],
|
||||
1475: [1,{GOLDEN_SPICE:[],CRYSTAL_SPICE:[1483,1485]},40],
|
||||
1476: [1,{GOLDEN_SPICE:[],CRYSTAL_SPICE:[1484,1486]},40],
|
||||
1477: [1,{GOLDEN_SPICE:[],CRYSTAL_SPICE:[1483,1485]},40],
|
||||
1478: [1,{GOLDEN_SPICE:[],CRYSTAL_SPICE:[1484,1486]},40],
|
||||
1479: [2,{GOLDEN_SPICE:[[1487,1488],[12785,12786]],CRYSTAL_SPICE:[]},25],
|
||||
1480: [2,{GOLDEN_SPICE:[[1487,1488],[12785,12786]],CRYSTAL_SPICE:[]},25],
|
||||
1481: [2,{GOLDEN_SPICE:[[1487,1488],[12785,12786]],CRYSTAL_SPICE:[]},25],
|
||||
1482: [2,{GOLDEN_SPICE:[[1487,1488],[12785,12786]],CRYSTAL_SPICE:[]},25],
|
||||
1483: [2,{GOLDEN_SPICE:[],CRYSTAL_SPICE:[[1487,1488],[12785,12786]]},25],
|
||||
1484: [2,{GOLDEN_SPICE:[],CRYSTAL_SPICE:[[1487,1488],[12785,12786]]},25],
|
||||
1485: [2,{GOLDEN_SPICE:[],CRYSTAL_SPICE:[[1487,1488],[12785,12786]]},25],
|
||||
1486: [2,{GOLDEN_SPICE:[],CRYSTAL_SPICE:[[1487,1488],[12785,12786]]},25],
|
||||
# Alpen Cougar
|
||||
1489: [0,{GOLDEN_SPICE:[1490,1491, 1492, 1493],CRYSTAL_SPICE:[1494,1495, 1496, 1497]},100],
|
||||
1490: [1,{GOLDEN_SPICE:[1498,1500],CRYSTAL_SPICE:[]},40],
|
||||
1491: [1,{GOLDEN_SPICE:[1499,1501],CRYSTAL_SPICE:[]},40],
|
||||
1492: [1,{GOLDEN_SPICE:[1498,1500],CRYSTAL_SPICE:[]},40],
|
||||
1493: [1,{GOLDEN_SPICE:[1499,1501],CRYSTAL_SPICE:[]},40],
|
||||
1494: [1,{GOLDEN_SPICE:[],CRYSTAL_SPICE:[1502,1504]},40],
|
||||
1495: [1,{GOLDEN_SPICE:[],CRYSTAL_SPICE:[1503,1505]},40],
|
||||
1496: [1,{GOLDEN_SPICE:[],CRYSTAL_SPICE:[1502,1504]},40],
|
||||
1497: [1,{GOLDEN_SPICE:[],CRYSTAL_SPICE:[1503,1505]},40],
|
||||
1498: [2,{GOLDEN_SPICE:[[1506,1507],[12787,12788]],CRYSTAL_SPICE:[]},25],
|
||||
1499: [2,{GOLDEN_SPICE:[[1506,1507],[12787,12788]],CRYSTAL_SPICE:[]},25],
|
||||
1500: [2,{GOLDEN_SPICE:[[1506,1507],[12787,12788]],CRYSTAL_SPICE:[]},25],
|
||||
1501: [2,{GOLDEN_SPICE:[[1506,1507],[12787,12788]],CRYSTAL_SPICE:[]},25],
|
||||
1502: [2,{GOLDEN_SPICE:[],CRYSTAL_SPICE:[[1506,1507],[12787,12788]]},25],
|
||||
1503: [2,{GOLDEN_SPICE:[],CRYSTAL_SPICE:[[1506,1507],[12787,12788]]},25],
|
||||
1504: [2,{GOLDEN_SPICE:[],CRYSTAL_SPICE:[[1506,1507],[12787,12788]]},25],
|
||||
1505: [2,{GOLDEN_SPICE:[],CRYSTAL_SPICE:[[1506,1507],[12787,12788]]},25]
|
||||
}
|
||||
self.Text = [["What did you just do to me?","You want to tame me, huh?","Do not give me this. Perhaps you will be in danger.","Bah bah. What is this unpalatable thing?","My belly has been complaining. This hit the spot.","What is this? Can I eat it?","You don't need to worry about me.","Delicious food, thanks.","I am starting to like you!","Gulp"],
|
||||
["I do not think you have given up on the idea of taming me.","That is just food to me. Perhaps I can eat your hand too.","Will eating this make me fat? Ha ha","Why do you always feed me?","Do not trust me. I may betray you"],
|
||||
["Destroy","Look what you have done!","Strange feeling...! Evil intentions grow in my heart...!","It is happenning!","This is sad...Good is sad...!"]]
|
||||
|
||||
self.feedInfo = {} # : feedInfo[objectId of mob] = objectId of player feeding it
|
||||
|
||||
for i in self.feedableBeasts :
|
||||
self.addSkillSeeId(i)
|
||||
self.addKillId(i)
|
||||
|
||||
def spawnNext(self, npc, growthLevel,player,food) :
|
||||
st = player.getQuestState("feedable_beasts")
|
||||
npcId = npc.getNpcId()
|
||||
nextNpcId = 0
|
||||
# find the next mob to spawn, based on the current npcId, growthlevel, and food.
|
||||
if growthLevel == 2:
|
||||
rand = Rnd.get(2)
|
||||
# if tamed, the mob that will spawn depends on the class type (fighter/mage) of the player!
|
||||
if rand == 1 :
|
||||
if player.getClassId().isMage() :
|
||||
nextNpcId = self.growthCapableMobs[npcId][1][food][1][1]
|
||||
else :
|
||||
nextNpcId = self.growthCapableMobs[npcId][1][food][1][0]
|
||||
# if not tamed, there is a small chance that have "mad cow" disease.
|
||||
# that is a stronger-than-normal animal that attacks its feeder
|
||||
else :
|
||||
if Rnd.get(5) == 0 :
|
||||
nextNpcId = self.growthCapableMobs[npcId][1][food][0][1]
|
||||
else :
|
||||
nextNpcId = self.growthCapableMobs[npcId][1][food][0][0]
|
||||
# all other levels of growth are straight-forward
|
||||
else :
|
||||
nextNpcId = self.growthCapableMobs[npcId][1][food][Rnd.get(len(self.growthCapableMobs[npcId][1][food]))]
|
||||
# remove the feedinfo of the mob that got despawned, if any
|
||||
if self.feedInfo.has_key(npc.getObjectId()) :
|
||||
if self.feedInfo[npc.getObjectId()] == player.getObjectId() :
|
||||
self.feedInfo.pop(npc.getObjectId())
|
||||
# despawn the old mob
|
||||
if self.growthCapableMobs[npcId][0] == 0 :
|
||||
npc.onDecay()
|
||||
else :
|
||||
npc.deleteMe()
|
||||
# if this is finally a trained mob, then despawn any other trained mobs that the
|
||||
# player might have and initialize the Tamed Beast.
|
||||
if nextNpcId in self.tamedBeasts :
|
||||
oldTrained = player.getTrainedBeast()
|
||||
if oldTrained :
|
||||
oldTrained.doDespawn()
|
||||
template = NpcTable.getInstance().getTemplate(nextNpcId)
|
||||
nextNpc = L2TamedBeastInstance(IdFactory.getInstance().getNextId(), template, player, foodSkill[food], npc.getX(), npc.getY(), npc.getZ())
|
||||
nextNpc.setRunning()
|
||||
objectId = nextNpc.getObjectId()
|
||||
st = player.getQuestState("20_BringUpWithLove")
|
||||
if st :
|
||||
if Rnd.get(100) <= 5 and st.getQuestItemsCount(7185) == 0 :
|
||||
st.giveItems(7185,1) #if player has quest 20 going, give quest item
|
||||
st.set("cond","2") #it's easier to hardcode it in here than to try and repeat this stuff in the quest
|
||||
# also, perform a rare random chat
|
||||
rand = Rnd.get(20)
|
||||
if rand > 4 : pass
|
||||
elif rand == 0 : npc.broadcastPacket(CreatureSay(objectId,0,nextNpc.getName(), player.getName()+", will you show me your hideaway?"))
|
||||
elif rand == 1 : npc.broadcastPacket(CreatureSay(objectId,0,nextNpc.getName(), player.getName()+", whenever I look at spice, I think about you."))
|
||||
elif rand == 2 : npc.broadcastPacket(CreatureSay(objectId,0,nextNpc.getName(), player.getName()+", you do not need to return to the village. I will give you strength"))
|
||||
elif rand == 3 : npc.broadcastPacket(CreatureSay(objectId,0,nextNpc.getName(), "Thanks, "+player.getName()+". I hope I can help you"))
|
||||
elif rand == 4 : npc.broadcastPacket(CreatureSay(objectId,0,nextNpc.getName(), player.getName()+", what can I do to help you?"))
|
||||
# if not trained, the newly spawned mob will automatically be agro against its feeder
|
||||
# (what happened to "never bite the hand that feeds you" anyway?!)
|
||||
else :
|
||||
# spawn the new mob
|
||||
nextNpc = self.addSpawn(nextNpcId,npc)
|
||||
# register the player in the feedinfo for the mob that just spawned
|
||||
self.feedInfo[nextNpc.getObjectId()] = player.getObjectId()
|
||||
nextNpc.setRunning()
|
||||
nextNpc.addDamageHate(player,0,99999)
|
||||
nextNpc.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, player)
|
||||
|
||||
def onSkillSee (self,npc,player,skill,targets,isPet):
|
||||
if npc not in targets :
|
||||
return
|
||||
# gather some values on local variables
|
||||
npcId = npc.getNpcId()
|
||||
skillId = skill.getId()
|
||||
# check if the npc and skills used are valid for this script. Exit if invalid.
|
||||
if npcId not in self.feedableBeasts : return
|
||||
if skillId not in [SKILL_GOLDEN_SPICE,SKILL_CRYSTAL_SPICE] :
|
||||
return
|
||||
# first gather some values on local variables
|
||||
objectId = npc.getObjectId()
|
||||
growthLevel = 3 # if a mob is in feedableBeasts but not in growthCapableMobs, then it's at max growth (3)
|
||||
if self.growthCapableMobs.has_key(npcId) :
|
||||
growthLevel = self.growthCapableMobs[npcId][0]
|
||||
# prevent exploit which allows 2 players to simultaneously raise the same 0-growth beast
|
||||
# If the mob is at 0th level (when it still listens to all feeders) lock it to the first feeder!
|
||||
if (growthLevel==0) and self.feedInfo.has_key(objectId):
|
||||
return
|
||||
else :
|
||||
self.feedInfo[objectId] = player.getObjectId()
|
||||
food = 0
|
||||
if skillId == SKILL_GOLDEN_SPICE :
|
||||
food = GOLDEN_SPICE
|
||||
elif skillId == SKILL_CRYSTAL_SPICE :
|
||||
food = CRYSTAL_SPICE
|
||||
# display the social action of the beast eating the food.
|
||||
npc.broadcastPacket(SocialAction(objectId,2))
|
||||
# if this pet can't grow, it's all done.
|
||||
if npcId in self.growthCapableMobs.keys() :
|
||||
# do nothing if this mob doesn't eat the specified food (food gets consumed but has no effect).
|
||||
if len(self.growthCapableMobs[npcId][1][food]) == 0 :
|
||||
return
|
||||
# rare random talk...
|
||||
if Rnd.get(20) == 0 :
|
||||
npc.broadcastPacket(CreatureSay(objectId,0,npc.getName(),self.Text[growthLevel][Rnd.get(len(self.Text[growthLevel]))]))
|
||||
if growthLevel > 0 :
|
||||
# check if this is the same player as the one who raised it from growth 0.
|
||||
# if no, then do not allow a chance to raise the pet (food gets consumed but has no effect).
|
||||
if self.feedInfo[objectId] != player.getObjectId() : return
|
||||
# Polymorph the mob, with a certain chance, given its current growth level
|
||||
if Rnd.get(100) < self.growthCapableMobs[npcId][2] :
|
||||
self.spawnNext(npc, growthLevel,player,food)
|
||||
elif npcId in self.tamedBeasts :
|
||||
if skillId == npc.getFoodType() :
|
||||
npc.onReceiveFood()
|
||||
mytext = ["Refills! Yeah!","I am such a gluttonous beast, it is embarrassing! Ha ha",
|
||||
"Your cooperative feeling has been getting better and better.",
|
||||
"I will help you!",
|
||||
"The weather is really good. Wanna go for a picnic?",
|
||||
"I really like you! This is tasty...",
|
||||
"If you do not have to leave this place, then I can help you.",
|
||||
"What can I help you with?",
|
||||
"I am not here only for food!",
|
||||
"Yam, yam, yam, yam, yam!"]
|
||||
npc.broadcastPacket(CreatureSay(objectId,0,npc.getName(),mytext[Rnd.get(len(mytext))]))
|
||||
return
|
||||
|
||||
def onKill (self,npc,player,isPet):
|
||||
# remove the feedinfo of the mob that got killed, if any
|
||||
if self.feedInfo.has_key(npc.getObjectId()) :
|
||||
self.feedInfo.pop(npc.getObjectId())
|
||||
|
||||
# now call the constructor (starts up the ai)
|
||||
QUEST = feedable_beasts(-1,"feedable_beasts","ai")
|
38
L2J_Mobius_C4/dist/game/data/scripts/ai/group_template/polymorphing_angel.py
vendored
Normal file
38
L2J_Mobius_C4/dist/game/data/scripts/ai/group_template/polymorphing_angel.py
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
import sys
|
||||
from com.l2jmobius.gameserver.ai import CtrlIntention
|
||||
from com.l2jmobius.gameserver.model.quest.jython import QuestJython as JQuest
|
||||
|
||||
# Angel spawns...when one of the angels in the keys dies, the other angel will spawn.
|
||||
|
||||
class polymorphing_angel(JQuest) :
|
||||
|
||||
# init function. Add in here variables that you'd like to be inherited by subclasses (if any)
|
||||
def __init__(self,id,name,descr):
|
||||
self.AngelSpawns ={
|
||||
830:859,
|
||||
1067:1068,
|
||||
1062:1063,
|
||||
831:860,
|
||||
1070:1071
|
||||
}
|
||||
# finally, don't forget to call the parent constructor to prepare the event triggering
|
||||
# mechanisms etc.
|
||||
JQuest.__init__(self,id,name,descr)
|
||||
|
||||
def onKill (self,npc,player,isPet):
|
||||
npcId = npc.getNpcId()
|
||||
if self.AngelSpawns.has_key(npcId) :
|
||||
newNpc = self.addSpawn(self.AngelSpawns[npcId],npc)
|
||||
killer = player
|
||||
if isPet :
|
||||
killer = player.getPet()
|
||||
newNpc.setRunning()
|
||||
newNpc.addDamageHate(killer,0,99999)
|
||||
newNpc.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, killer)
|
||||
return
|
||||
|
||||
# now call the constructor (starts up the ai)
|
||||
QUEST = polymorphing_angel(-1,"polymorphing_angel","ai")
|
||||
|
||||
for i in QUEST.AngelSpawns.keys() :
|
||||
QUEST.addKillId(i)
|
49
L2J_Mobius_C4/dist/game/data/scripts/ai/group_template/polymorphing_onAttack.py
vendored
Normal file
49
L2J_Mobius_C4/dist/game/data/scripts/ai/group_template/polymorphing_onAttack.py
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
import sys
|
||||
from com.l2jmobius.gameserver.ai import CtrlIntention
|
||||
from com.l2jmobius.gameserver.model.quest.jython import QuestJython as JQuest
|
||||
from com.l2jmobius.util import Rnd
|
||||
|
||||
class polymorphing_onAttack(JQuest) :
|
||||
# init function. Add in here variables that you'd like to be inherited by subclasses (if any)
|
||||
def __init__(self,id,name,descr):
|
||||
self.MobSpawns ={
|
||||
1258: [1259, 100, 100], #Fallen Orc Shaman -> Sharp Talon Tiger
|
||||
1261: [1262, 100, 20], #Ol Mahum Transcender 1st stage
|
||||
1262: [1263, 100, 10], #Ol Mahum Transcender 2st stage
|
||||
1263: [1264, 100, 5], #Ol Mahum Transcender 3rd stage
|
||||
1265: [1271, 100, 33], #Cave Ant Larva -> Cave Ant
|
||||
1266: [1269, 100, 100], #Cave Ant Larva -> Cave Ant (always polymorphs)
|
||||
1267: [1270, 100, 100], #Cave Ant Larva -> Cave Ant Soldier (always polymorphs)
|
||||
1271: [1272, 66, 10], #Cave Ant -> Cave Ant Soldier
|
||||
1272: [1273, 33, 5], #Cave Ant Soldier -> Cave Noble Ant
|
||||
1521: [1522, 100, 30], #Claws of Splendor -> Claws of Splendor Panther
|
||||
1524: [1525, 100, 30], #Blade of Splendor -> Blade of Splendor 2nd
|
||||
1527: [1528, 100, 30], #Anger of Splendor -> Anger of Splendor Panther
|
||||
1533: [1534, 100, 30], #Alliance of Splendor -> Alliance of Splendor Panther
|
||||
1537: [1538, 100, 30] #Fang of Splendor -> Fang of Splendor Panther
|
||||
}
|
||||
# finally, don't forget to call the parent constructor to prepare the event triggering
|
||||
# mechanisms etc.
|
||||
JQuest.__init__(self,id,name,descr)
|
||||
|
||||
def onAttack(self,npc,player,damage,isPet) :
|
||||
if npc.isVisible() and not npc.isDead() :
|
||||
newId,hpRate,chance = self.MobSpawns[npc.getNpcId()]
|
||||
if npc.getCurrentHp() <= (npc.getMaxHp() * hpRate/100.0) and Rnd.get(100) < chance :
|
||||
# It's the only way for 1st level mob to respawn after it's deleted
|
||||
npc.doDie(npc)
|
||||
npc.deleteMe()
|
||||
newNpc = self.addSpawn(newId,npc)
|
||||
killer = player
|
||||
if isPet :
|
||||
killer = player.getPet()
|
||||
newNpc.setRunning()
|
||||
newNpc.addDamageHate(killer,0,99999)
|
||||
newNpc.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, killer)
|
||||
return
|
||||
|
||||
# now call the constructor (starts up the ai)
|
||||
QUEST = polymorphing_onAttack(-1,"polymorphing_onAttack","ai")
|
||||
|
||||
for i in QUEST.MobSpawns.keys() :
|
||||
QUEST.addAttackId(i)
|
246
L2J_Mobius_C4/dist/game/data/scripts/ai/individual/Antharas.java
vendored
Normal file
246
L2J_Mobius_C4/dist/game/data/scripts/ai/individual/Antharas.java
vendored
Normal file
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* 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 ai.individual;
|
||||
|
||||
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
||||
import com.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||
import com.l2jmobius.gameserver.model.L2CharPosition;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2GrandBossInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2NpcInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.quest.Quest;
|
||||
import com.l2jmobius.gameserver.model.zone.type.L2BossZone;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.Earthquake;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.SpecialCamera;
|
||||
import com.l2jmobius.gameserver.templates.StatsSet;
|
||||
import com.l2jmobius.util.Rnd;
|
||||
|
||||
/**
|
||||
* Antharas AI
|
||||
* @author Emperorc
|
||||
*/
|
||||
public class Antharas extends Quest
|
||||
{
|
||||
private static final int ANTHARAS = 12211;
|
||||
|
||||
// Antharas Status Tracking :
|
||||
private static final byte DORMANT = 0; // Antharas is spawned and no one has entered yet. Entry is unlocked
|
||||
private static final byte WAITING = 1; // Antharas is spawned and someone has entered, triggering a 30 minute window for additional people to enter before he unleashes his attack. Entry is unlocked
|
||||
private static final byte FIGHTING = 2; // Antharas is engaged in battle, annihilating his foes. Entry is locked
|
||||
private static final byte DEAD = 3; // Antharas has been killed. Entry is locked
|
||||
|
||||
private static long _LastAction = 0;
|
||||
|
||||
private static L2BossZone _Zone;
|
||||
|
||||
// Boss: Antharas
|
||||
public Antharas(int id, String name, String descr)
|
||||
{
|
||||
super(id, name, descr);
|
||||
final int[] mob =
|
||||
{
|
||||
ANTHARAS
|
||||
};
|
||||
registerMobs(mob);
|
||||
_Zone = GrandBossManager.getInstance().getZone(179700, 113800, -7709);
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(ANTHARAS);
|
||||
final int status = GrandBossManager.getInstance().getBossStatus(ANTHARAS);
|
||||
if (status == DEAD)
|
||||
{
|
||||
// load the unlock date and time for antharas from DB
|
||||
// if antharas is locked until a certain time, mark it so and start the unlock timer
|
||||
// the unlock time has not yet expired. Mark Antharas as currently locked. Setup a timer
|
||||
// to fire at the correct time (calculate the time between now and the unlock time,
|
||||
// setup a timer to fire after that many msec)
|
||||
final long temp = (info.getLong("respawn_time") - System.currentTimeMillis());
|
||||
if (temp > 0)
|
||||
{
|
||||
startQuestTimer("antharas_unlock", temp, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// the time has already expired while the server was offline. Immediately spawn antharas in his cave.
|
||||
// also, the status needs to be changed to DORMANT
|
||||
final L2GrandBossInstance antharas = (L2GrandBossInstance) addSpawn(ANTHARAS, 185708, 114298, -8221, 32768, false, 0);
|
||||
GrandBossManager.getInstance().setBossStatus(ANTHARAS, DORMANT);
|
||||
antharas.broadcastPacket(new Earthquake(185708, 114298, -8221, 20, 10));
|
||||
GrandBossManager.getInstance().addBoss(antharas);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
final int loc_x = info.getInteger("loc_x");
|
||||
final int loc_y = info.getInteger("loc_y");
|
||||
final int loc_z = info.getInteger("loc_z");
|
||||
final int heading = info.getInteger("heading");
|
||||
final int hp = info.getInteger("currentHP");
|
||||
final int mp = info.getInteger("currentMP");
|
||||
final L2GrandBossInstance antharas = (L2GrandBossInstance) addSpawn(ANTHARAS, loc_x, loc_y, loc_z, heading, false, 0);
|
||||
GrandBossManager.getInstance().addBoss(antharas);
|
||||
antharas.setCurrentHpMp(hp, mp);
|
||||
if (status == WAITING)
|
||||
{
|
||||
// Start timer to lock entry after 30 minutes
|
||||
startQuestTimer("waiting", 1800000, antharas, null);
|
||||
}
|
||||
else if (status == FIGHTING)
|
||||
{
|
||||
_LastAction = System.currentTimeMillis();
|
||||
// Start repeating timer to check for inactivity
|
||||
startQuestTimer("antharas_despawn", 60000, antharas, null, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2NpcInstance npc, L2PcInstance player)
|
||||
{
|
||||
if (npc != null)
|
||||
{
|
||||
long temp = 0;
|
||||
if (event.equalsIgnoreCase("waiting"))
|
||||
{
|
||||
npc.teleToLocation(185452, 114835, -8221);
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new L2CharPosition(181911, 114835, -7678, 0));
|
||||
startQuestTimer("antharas_has_arrived", 2000, npc, null, true);
|
||||
npc.broadcastPacket(new PlaySound(1, "BS02_A", 1, npc.getObjectId(), 185452, 114835, -8221));
|
||||
GrandBossManager.getInstance().setBossStatus(ANTHARAS, FIGHTING);
|
||||
}
|
||||
else if (event.equalsIgnoreCase("camera_1"))
|
||||
{
|
||||
startQuestTimer("camera_2", 3000, npc, null);
|
||||
npc.broadcastPacket(new SpecialCamera(npc.getObjectId(), 700, 13, -19, 0, 20000, 0, 0, 1, 0));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("camera_2"))
|
||||
{
|
||||
startQuestTimer("camera_3", 10000, npc, null);
|
||||
npc.broadcastPacket(new SpecialCamera(npc.getObjectId(), 700, 13, 0, 6000, 20000, 0, 0, 1, 0));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("camera_3"))
|
||||
{
|
||||
startQuestTimer("camera_4", 200, npc, null);
|
||||
npc.broadcastPacket(new SpecialCamera(npc.getObjectId(), 3700, 0, -3, 0, 10000, 0, 0, 1, 0));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("camera_4"))
|
||||
{
|
||||
startQuestTimer("camera_5", 10800, npc, null);
|
||||
npc.broadcastPacket(new SpecialCamera(npc.getObjectId(), 1100, 0, -3, 22000, 30000, 0, 0, 1, 0));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("camera_5"))
|
||||
{
|
||||
startQuestTimer("antharas_despawn", 60000, npc, null, true);
|
||||
npc.broadcastPacket(new SpecialCamera(npc.getObjectId(), 1100, 0, -3, 300, 7000, 0, 0, 1, 0));
|
||||
npc.setIsImmobilized(false);
|
||||
_LastAction = System.currentTimeMillis();
|
||||
}
|
||||
else if (event.equalsIgnoreCase("antharas_despawn"))
|
||||
{
|
||||
temp = (System.currentTimeMillis() - _LastAction);
|
||||
if (temp > 1800000)
|
||||
{
|
||||
npc.teleToLocation(185708, 114298, -8221);
|
||||
GrandBossManager.getInstance().setBossStatus(ANTHARAS, DORMANT);
|
||||
npc.setCurrentHpMp(npc.getMaxHp(), npc.getMaxMp());
|
||||
_Zone.oustAllPlayers();
|
||||
cancelQuestTimer("antharas_despawn", npc, null);
|
||||
}
|
||||
}
|
||||
else if (event.equalsIgnoreCase("antharas_has_arrived"))
|
||||
{
|
||||
final int dx = Math.abs(npc.getX() - 181911);
|
||||
final int dy = Math.abs(npc.getY() - 114835);
|
||||
if ((dx <= 50) && (dy <= 50))
|
||||
{
|
||||
startQuestTimer("camera_1", 2000, npc, null);
|
||||
npc.getSpawn().setLocx(181911);
|
||||
npc.getSpawn().setLocy(114835);
|
||||
npc.getSpawn().setLocz(-7678);
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
|
||||
npc.setIsImmobilized(true);
|
||||
cancelQuestTimer("antharas_has_arrived", npc, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new L2CharPosition(181911, 114835, -7678, 0));
|
||||
}
|
||||
}
|
||||
else if (event.equalsIgnoreCase("spawn_cubes"))
|
||||
{
|
||||
addSpawn(12324, 177615, 114941, -7709, 0, false, 900000);
|
||||
final int radius = 1500;
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
final int x = (int) (radius * Math.cos(i * .331)); // .331~2pi/19
|
||||
final int y = (int) (radius * Math.sin(i * .331));
|
||||
addSpawn(31859, 177615 + x, 114941 + y, -7709, 0, false, 900000);
|
||||
}
|
||||
cancelQuestTimer("antharas_despawn", npc, null);
|
||||
startQuestTimer("remove_players", 900000, null, null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (event.equalsIgnoreCase("antharas_unlock"))
|
||||
{
|
||||
final L2GrandBossInstance antharas = (L2GrandBossInstance) addSpawn(ANTHARAS, 185708, 114298, -8221, 32768, false, 0);
|
||||
GrandBossManager.getInstance().addBoss(antharas);
|
||||
GrandBossManager.getInstance().setBossStatus(ANTHARAS, DORMANT);
|
||||
antharas.broadcastPacket(new Earthquake(185708, 114298, -8221, 20, 10));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("remove_players"))
|
||||
{
|
||||
_Zone.oustAllPlayers();
|
||||
}
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2NpcInstance npc, L2PcInstance attacker, int damage, boolean isPet)
|
||||
{
|
||||
_LastAction = System.currentTimeMillis();
|
||||
if (GrandBossManager.getInstance().getBossStatus(ANTHARAS) != FIGHTING)
|
||||
{
|
||||
attacker.teleToLocation(82480, 149087, -3350, true);
|
||||
}
|
||||
|
||||
return super.onAttack(npc, attacker, damage, isPet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2NpcInstance npc, L2PcInstance killer, boolean isPet)
|
||||
{
|
||||
npc.broadcastPacket(new SpecialCamera(npc.getObjectId(), 1200, 20, -10, 0, 13000, 0, 0, 1, 0));
|
||||
npc.broadcastPacket(new PlaySound(1, "BS01_D", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
|
||||
startQuestTimer("spawn_cubes", 10000, npc, null);
|
||||
GrandBossManager.getInstance().setBossStatus(ANTHARAS, DEAD);
|
||||
final long respawnTime = ((192 + Rnd.get(145)) * 3600000);
|
||||
startQuestTimer("antharas_unlock", respawnTime, null, null);
|
||||
// also save the respawn time so that the info is maintained past reboots
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(ANTHARAS);
|
||||
info.set("respawn_time", (System.currentTimeMillis() + respawnTime));
|
||||
GrandBossManager.getInstance().setStatsSet(ANTHARAS, info);
|
||||
return super.onKill(npc, killer, isPet);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
// now call the constructor (starts up the ai)
|
||||
new Antharas(-1, "antharas", "ai");
|
||||
}
|
||||
}
|
697
L2J_Mobius_C4/dist/game/data/scripts/ai/individual/Baium.java
vendored
Normal file
697
L2J_Mobius_C4/dist/game/data/scripts/ai/individual/Baium.java
vendored
Normal file
@@ -0,0 +1,697 @@
|
||||
/*
|
||||
* 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 ai.individual;
|
||||
|
||||
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_FOLLOW;
|
||||
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import com.l2jmobius.gameserver.GeoData;
|
||||
import com.l2jmobius.gameserver.ThreadPoolManager;
|
||||
import com.l2jmobius.gameserver.datatables.SkillTable;
|
||||
import com.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||
import com.l2jmobius.gameserver.model.L2Character;
|
||||
import com.l2jmobius.gameserver.model.L2Effect;
|
||||
import com.l2jmobius.gameserver.model.L2Object;
|
||||
import com.l2jmobius.gameserver.model.L2Skill;
|
||||
import com.l2jmobius.gameserver.model.L2Summon;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2GrandBossInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2NpcInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.quest.Quest;
|
||||
import com.l2jmobius.gameserver.model.quest.QuestState;
|
||||
import com.l2jmobius.gameserver.model.quest.QuestTimer;
|
||||
import com.l2jmobius.gameserver.model.quest.State;
|
||||
import com.l2jmobius.gameserver.model.zone.type.L2BossZone;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.Earthquake;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.MoveToPawn;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.SocialAction;
|
||||
import com.l2jmobius.gameserver.templates.StatsSet;
|
||||
import com.l2jmobius.gameserver.util.Util;
|
||||
import com.l2jmobius.util.Rnd;
|
||||
|
||||
import javolution.util.FastList;
|
||||
|
||||
/**
|
||||
* Baium AI Note1: if the server gets rebooted while players are still fighting Baium, there is no lock, but players also lose their ability to wake baium up. However, should another person enter the room and wake him up, the players who had stayed inside may join the raid. This can be helpful for
|
||||
* players who became victims of a reboot (they only need 1 new player to enter and wake up baium) and is not too exploitable since any player wishing to exploit it would have to suffer 5 days of being parked in an empty room. Note2: Neither version of Baium should be a permanent spawn. This script
|
||||
* is fully capable of spawning the statue-version when the lock expires and switching it to the mob version promptly. Additional notes ( source http://aleenaresron.blogspot.com/2006_08_01_archive.html ): * Baium only first respawns five days after his last death. And from those five days he will
|
||||
* respawn within 1-8 hours of his last death. So, you have to know his last time of death. * If by some freak chance you are the only one in Baium's chamber and NO ONE comes in [ha, ha] you or someone else will have to wake Baium. There is a good chance that Baium will automatically kill whoever
|
||||
* wakes him. There are some people that have been able to wake him and not die, however if you've already gone through the trouble of getting the bloody fabric and camped him out and researched his spawn time, are you willing to take that chance that you'll wake him and not be able to finish your
|
||||
* quest? Doubtful. [ this powerful attack vs the player who wakes him up is NOT yet implemented here] * once someone starts attacking Baium no one else can port into the chamber where he is. Unlike with the other raid bosses, you can just show up at any time as long as you are there when they die.
|
||||
* Not true with Baium. Once he gets attacked, the port to Baium closes. byebye, see you in 5 days. If nobody attacks baium for 30 minutes, he auto-despawns and unlocks the vortex
|
||||
* @author Fulminus version 0.1
|
||||
*/
|
||||
public class Baium extends Quest
|
||||
{
|
||||
private L2Character _target;
|
||||
private L2Skill _skill;
|
||||
private static final int STONE_BAIUM = 12535;
|
||||
private static final int ANGELIC_VORTEX = 12571;
|
||||
private static final int LIVE_BAIUM = 12372;
|
||||
private static final int ARCHANGEL = 12373;
|
||||
|
||||
// Baium status tracking
|
||||
private static final byte ASLEEP = 0; // baium is in the stone version, waiting to be woken up. Entry is unlocked
|
||||
private static final byte AWAKE = 1; // baium is awake and fighting. Entry is locked.
|
||||
private static final byte DEAD = 2; // baium has been killed and has not yet spawned. Entry is locked
|
||||
|
||||
// fixed archangel spawnloc
|
||||
private final static int ANGEL_LOCATION[][] =
|
||||
{
|
||||
{
|
||||
114239,
|
||||
17168,
|
||||
10080,
|
||||
63544
|
||||
},
|
||||
{
|
||||
115780,
|
||||
15564,
|
||||
10080,
|
||||
13620
|
||||
},
|
||||
{
|
||||
114880,
|
||||
16236,
|
||||
10080,
|
||||
5400
|
||||
},
|
||||
{
|
||||
115168,
|
||||
17200,
|
||||
10080,
|
||||
0
|
||||
},
|
||||
{
|
||||
115792,
|
||||
16608,
|
||||
10080,
|
||||
0
|
||||
}
|
||||
};
|
||||
|
||||
private long _LastAttackVsBaiumTime = 0;
|
||||
private final List<L2NpcInstance> _Minions = new ArrayList<>(5);
|
||||
private L2BossZone _Zone;
|
||||
|
||||
public Baium(int questId, String name, String descr)
|
||||
{
|
||||
super(questId, name, descr);
|
||||
|
||||
// set initial state
|
||||
setInitialState(new State("Start", this));
|
||||
|
||||
final int[] mob =
|
||||
{
|
||||
LIVE_BAIUM
|
||||
};
|
||||
registerMobs(mob);
|
||||
|
||||
// Quest NPC starter initialization
|
||||
addStartNpc(STONE_BAIUM);
|
||||
addStartNpc(ANGELIC_VORTEX);
|
||||
addTalkId(STONE_BAIUM);
|
||||
addTalkId(ANGELIC_VORTEX);
|
||||
|
||||
_Zone = GrandBossManager.getInstance().getZone(113100, 14500, 10077);
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(LIVE_BAIUM);
|
||||
final int status = GrandBossManager.getInstance().getBossStatus(LIVE_BAIUM);
|
||||
if (status == DEAD)
|
||||
{
|
||||
// load the unlock date and time for baium from DB
|
||||
final long temp = (info.getLong("respawn_time") - System.currentTimeMillis());
|
||||
if (temp > 0)
|
||||
{
|
||||
// the unlock time has not yet expired. Mark Baium as currently locked (dead). Setup a timer
|
||||
// to fire at the correct time (calculate the time between now and the unlock time,
|
||||
// setup a timer to fire after that many msec)
|
||||
startQuestTimer("baium_unlock", temp, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// the time has already expired while the server was offline. Delete the saved time and
|
||||
// immediately spawn the stone-baium. Also the state need not be changed from ASLEEP
|
||||
addSpawn(STONE_BAIUM, 116063, 17508, 10080, 41740, false, 0);
|
||||
GrandBossManager.getInstance().setBossStatus(LIVE_BAIUM, ASLEEP);
|
||||
}
|
||||
}
|
||||
else if (status == AWAKE)
|
||||
{
|
||||
final int loc_x = info.getInteger("loc_x");
|
||||
final int loc_y = info.getInteger("loc_y");
|
||||
final int loc_z = info.getInteger("loc_z");
|
||||
final int heading = info.getInteger("heading");
|
||||
final int hp = info.getInteger("currentHP");
|
||||
final int mp = info.getInteger("currentMP");
|
||||
final L2GrandBossInstance baium = (L2GrandBossInstance) addSpawn(LIVE_BAIUM, loc_x, loc_y, loc_z, heading, false, 0);
|
||||
GrandBossManager.getInstance().addBoss(baium);
|
||||
final L2NpcInstance _baium = baium;
|
||||
ThreadPoolManager.getInstance().scheduleGeneral(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
_baium.setCurrentHpMp(hp, mp);
|
||||
_baium.setIsInvul(true);
|
||||
_baium.setIsImmobilized(true);
|
||||
_baium.setRunning();
|
||||
_baium.broadcastPacket(new SocialAction(_baium.getObjectId(), 2));
|
||||
startQuestTimer("baium_wakeup", 15000, _baium, null);
|
||||
}
|
||||
catch (final Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}, 100L);
|
||||
}
|
||||
else
|
||||
{
|
||||
addSpawn(STONE_BAIUM, 116063, 17508, 10080, 41740, false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2NpcInstance npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equalsIgnoreCase("baium_unlock"))
|
||||
{
|
||||
GrandBossManager.getInstance().setBossStatus(LIVE_BAIUM, ASLEEP);
|
||||
addSpawn(STONE_BAIUM, 116063, 17508, 10080, 41740, false, 0);
|
||||
}
|
||||
else if (event.equalsIgnoreCase("skill_range") && (npc != null))
|
||||
{
|
||||
callSkillAI(npc);
|
||||
}
|
||||
else if (event.equalsIgnoreCase("clean_player"))
|
||||
{
|
||||
_target = getRandomTarget(npc);
|
||||
}
|
||||
else if (event.equalsIgnoreCase("baium_wakeup") && (npc != null))
|
||||
{
|
||||
if (npc.getNpcId() == LIVE_BAIUM)
|
||||
{
|
||||
npc.broadcastPacket(new SocialAction(npc.getObjectId(), 1));
|
||||
npc.broadcastPacket(new Earthquake(npc.getX(), npc.getY(), npc.getZ(), 40, 5));
|
||||
// start monitoring baium's inactivity
|
||||
_LastAttackVsBaiumTime = System.currentTimeMillis();
|
||||
startQuestTimer("baium_despawn", 60000, npc, null, true);
|
||||
startQuestTimer("skill_range", 500, npc, null, true);
|
||||
final L2NpcInstance baium = npc;
|
||||
ThreadPoolManager.getInstance().scheduleGeneral(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
baium.setIsInvul(false);
|
||||
baium.setIsImmobilized(false);
|
||||
}
|
||||
catch (final Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}, 11100L);
|
||||
|
||||
// TODO: the person who woke baium up should be knocked across the room, onto a wall, and
|
||||
// lose massive amounts of HP.
|
||||
|
||||
for (final int[] element : ANGEL_LOCATION)
|
||||
{
|
||||
final L2NpcInstance angel = addSpawn(ARCHANGEL, element[0], element[1], element[2], element[3], false, 0);
|
||||
angel.setIsInvul(true);
|
||||
_Minions.add(angel);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event.equalsIgnoreCase("baium_despawn") && (npc != null))
|
||||
{
|
||||
// despawn the live baium after 30 minutes of inactivity
|
||||
// also check if the players are cheating, having pulled Baium outside his zone...
|
||||
if (npc.getNpcId() == LIVE_BAIUM)
|
||||
{
|
||||
// just in case the zone reference has been lost (somehow...), restore the reference
|
||||
if (_Zone == null)
|
||||
{
|
||||
_Zone = GrandBossManager.getInstance().getZone(113100, 14500, 10077);
|
||||
}
|
||||
if ((_LastAttackVsBaiumTime + 1800000) < System.currentTimeMillis())
|
||||
{
|
||||
npc.deleteMe(); // despawn the live-baium
|
||||
|
||||
for (final L2NpcInstance minion : _Minions)
|
||||
{
|
||||
if (minion != null)
|
||||
{
|
||||
minion.getSpawn().stopRespawn();
|
||||
minion.deleteMe();
|
||||
}
|
||||
}
|
||||
|
||||
addSpawn(STONE_BAIUM, 116063, 17508, 10080, 41740, false, 0); // spawn stone-baium
|
||||
GrandBossManager.getInstance().setBossStatus(LIVE_BAIUM, ASLEEP); // mark that Baium is not awake any more
|
||||
_Zone.oustAllPlayers();
|
||||
cancelQuestTimer("baium_despawn", npc, null);
|
||||
}
|
||||
else if (((_LastAttackVsBaiumTime + 300000) < System.currentTimeMillis()) && (npc.getCurrentHp() < ((npc.getMaxHp() * 3) / 4)))
|
||||
{
|
||||
npc.setTarget(npc);
|
||||
npc.doCast(SkillTable.getInstance().getInfo(4135, 1));
|
||||
}
|
||||
else if (!_Zone.isInsideZone(npc))
|
||||
{
|
||||
npc.teleToLocation(115213, 16623, 10080);
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onTalk(L2NpcInstance npc, QuestState st)
|
||||
{
|
||||
final int npcId = npc.getNpcId();
|
||||
if (_Zone == null)
|
||||
{
|
||||
_Zone = GrandBossManager.getInstance().getZone(113100, 14500, 10077);
|
||||
}
|
||||
if (_Zone == null)
|
||||
{
|
||||
return "<html><body>Angelic Vortex:<br>You may not enter while admin disabled this zone</body></html>";
|
||||
}
|
||||
if ((npcId == STONE_BAIUM) && (GrandBossManager.getInstance().getBossStatus(LIVE_BAIUM) == ASLEEP))
|
||||
{
|
||||
if (_Zone.checkIfPlayerAllowed(st.getPlayer()))
|
||||
{
|
||||
// once Baium is awaken, no more people may enter until he dies, the server reboots, or
|
||||
// 30 minutes pass with no attacks made against Baium.
|
||||
GrandBossManager.getInstance().setBossStatus(LIVE_BAIUM, AWAKE);
|
||||
npc.deleteMe();
|
||||
final L2GrandBossInstance baium = (L2GrandBossInstance) addSpawn(LIVE_BAIUM, npc);
|
||||
GrandBossManager.getInstance().addBoss(baium);
|
||||
final L2NpcInstance _baium = baium;
|
||||
ThreadPoolManager.getInstance().scheduleGeneral(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
_baium.setIsInvul(true);
|
||||
_baium.setIsImmobilized(true);
|
||||
_baium.setRunning();
|
||||
_baium.broadcastPacket(new SocialAction(_baium.getObjectId(), 2));
|
||||
startQuestTimer("baium_wakeup", 15000, _baium, null);
|
||||
}
|
||||
catch (final Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}, 100L);
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Conditions are not right to wake up Baium.";
|
||||
}
|
||||
}
|
||||
else if (npcId == ANGELIC_VORTEX)
|
||||
{
|
||||
if (GrandBossManager.getInstance().getBossStatus(LIVE_BAIUM) == ASLEEP)
|
||||
{
|
||||
if (st.getPlayer().isFlying())
|
||||
{
|
||||
return "<html><body>Angelic Vortex:<br>You may not enter while flying a wyvern.</body></html>";
|
||||
}
|
||||
else if (st.getQuestItemsCount(4295) > 0) // bloody fabric
|
||||
{
|
||||
st.takeItems(4295, 1);
|
||||
// allow entry for the player for the next 30 secs (more than enough time for the TP to happen)
|
||||
// Note: this just means 30secs to get in, no limits on how long it takes before we get out.
|
||||
_Zone.allowPlayerEntry(st.getPlayer(), 30);
|
||||
st.getPlayer().teleToLocation(113100, 14500, 10077);
|
||||
}
|
||||
else
|
||||
{
|
||||
return "<html><body>Angelic Vortex:<br>You do not have enough items.</body></html>";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return "<html><body>Angelic Vortex:<br>You may not enter at this time.</body></html>";
|
||||
}
|
||||
}
|
||||
st.exitQuest(true);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpellFinished(L2NpcInstance npc, L2PcInstance player, L2Skill skill)
|
||||
{
|
||||
if (npc.isInvul())
|
||||
{
|
||||
npc.getAI().setIntention(AI_INTENTION_IDLE);
|
||||
return null;
|
||||
}
|
||||
else if ((npc.getNpcId() == LIVE_BAIUM) && !npc.isInvul())
|
||||
{
|
||||
callSkillAI(npc);
|
||||
}
|
||||
return super.onSpellFinished(npc, player, skill);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2NpcInstance npc)
|
||||
{
|
||||
npc.disableCoreAI(true);
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2NpcInstance npc, L2PcInstance attacker, int damage, boolean isPet)
|
||||
{
|
||||
if (!_Zone.isInsideZone(attacker))
|
||||
{
|
||||
attacker.reduceCurrentHp(attacker.getCurrentHp(), attacker, false);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (npc.isInvul())
|
||||
{
|
||||
npc.getAI().setIntention(AI_INTENTION_IDLE);
|
||||
return null;
|
||||
}
|
||||
else if ((npc.getNpcId() == LIVE_BAIUM) && !npc.isInvul())
|
||||
{
|
||||
if (attacker.getMountType() == 1)
|
||||
{
|
||||
int sk_4258 = 0;
|
||||
final L2Effect[] effects = attacker.getAllEffects();
|
||||
if (effects.length != 0)
|
||||
{
|
||||
for (final L2Effect e : effects)
|
||||
{
|
||||
if (e.getSkill().getId() == 4258)
|
||||
{
|
||||
sk_4258 = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sk_4258 == 0)
|
||||
{
|
||||
npc.setTarget(attacker);
|
||||
npc.doCast(SkillTable.getInstance().getInfo(4258, 1));
|
||||
}
|
||||
}
|
||||
|
||||
// update a variable with the last action against baium
|
||||
_LastAttackVsBaiumTime = System.currentTimeMillis();
|
||||
callSkillAI(npc);
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isPet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2NpcInstance npc, L2PcInstance killer, boolean isPet)
|
||||
{
|
||||
cancelQuestTimer("baium_despawn", npc, null);
|
||||
npc.broadcastPacket(new PlaySound(1, "BS01_D", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
|
||||
// spawn the "Teleportation Cubic" for 15 minutes (to allow players to exit the lair)
|
||||
addSpawn(12078, 115203, 16620, 10078, 0, false, 900000); //// should we teleport everyone out if the cubic despawns??
|
||||
// "lock" baium for 5 days and 1 to 8 hours [i.e. 432,000,000 + 1*3,600,000 + random-less-than(8*3,600,000) millisecs]
|
||||
final long respawnTime = ((121 + Rnd.get(8)) * 3600000);
|
||||
GrandBossManager.getInstance().setBossStatus(LIVE_BAIUM, DEAD);
|
||||
startQuestTimer("baium_unlock", respawnTime, null, null);
|
||||
// also save the respawn time so that the info is maintained past reboots
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(LIVE_BAIUM);
|
||||
info.set("respawn_time", (System.currentTimeMillis()) + respawnTime);
|
||||
GrandBossManager.getInstance().setStatsSet(LIVE_BAIUM, info);
|
||||
|
||||
for (final L2NpcInstance minion : _Minions)
|
||||
{
|
||||
if (minion != null)
|
||||
{
|
||||
minion.getSpawn().stopRespawn();
|
||||
minion.deleteMe();
|
||||
}
|
||||
}
|
||||
|
||||
if (getQuestTimer("skill_range", npc, null) != null)
|
||||
{
|
||||
getQuestTimer("skill_range", npc, null).cancel();
|
||||
}
|
||||
|
||||
return super.onKill(npc, killer, isPet);
|
||||
}
|
||||
|
||||
public L2Character getRandomTarget(L2NpcInstance npc)
|
||||
{
|
||||
final FastList<L2Character> result = new FastList<>();
|
||||
final Collection<L2Object> objs = npc.getKnownList().getKnownObjects().values();
|
||||
{
|
||||
for (final L2Object obj : objs)
|
||||
{
|
||||
if (obj instanceof L2Character)
|
||||
{
|
||||
if (((((L2Character) obj).getZ() < (npc.getZ() - 100)) && (((L2Character) obj).getZ() > (npc.getZ() + 100))) || !(GeoData.getInstance().canSeeTarget(((L2Character) obj).getX(), ((L2Character) obj).getY(), ((L2Character) obj).getZ(), npc.getX(), npc.getY(), npc.getZ())) || ((L2Character) obj).isGM())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ((obj instanceof L2PcInstance) || (obj instanceof L2Summon))
|
||||
{
|
||||
if (Util.checkIfInRange(9000, npc, obj, true) && !((L2Character) obj).isDead())
|
||||
{
|
||||
result.add((L2PcInstance) obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result.isEmpty())
|
||||
{
|
||||
for (final L2NpcInstance minion : _Minions)
|
||||
{
|
||||
if (minion != null)
|
||||
{
|
||||
result.add(minion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result.isEmpty())
|
||||
{
|
||||
FastList.recycle(result);
|
||||
return null;
|
||||
}
|
||||
|
||||
final Object[] characters = result.toArray();
|
||||
final QuestTimer timer = getQuestTimer("clean_player", npc, null);
|
||||
if (timer != null)
|
||||
{
|
||||
timer.cancel();
|
||||
}
|
||||
startQuestTimer("clean_player", 20000, npc, null);
|
||||
final L2Character target = (L2Character) characters[Rnd.get(characters.length)];
|
||||
FastList.recycle(result);
|
||||
return target;
|
||||
}
|
||||
|
||||
public synchronized void callSkillAI(L2NpcInstance npc)
|
||||
{
|
||||
if (npc.isInvul() || npc.isCastingNow())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((_target == null) || _target.isDead() || !(_Zone.isInsideZone(_target)))
|
||||
{
|
||||
_target = getRandomTarget(npc);
|
||||
if (_target != null)
|
||||
{
|
||||
_skill = SkillTable.getInstance().getInfo(getRandomSkill(npc), 1);
|
||||
}
|
||||
}
|
||||
|
||||
final L2Character target = _target;
|
||||
L2Skill skill = _skill;
|
||||
if (skill == null)
|
||||
{
|
||||
skill = SkillTable.getInstance().getInfo(getRandomSkill(npc), 1);
|
||||
}
|
||||
if ((target == null) || target.isDead() || !(_Zone.isInsideZone(target)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Util.checkIfInRange(skill.getCastRange(), npc, target, true))
|
||||
{
|
||||
npc.getAI().setIntention(AI_INTENTION_IDLE);
|
||||
npc.setTarget(target);
|
||||
_target = null;
|
||||
_skill = null;
|
||||
if (getDist(skill.getCastRange()) > 0)
|
||||
{
|
||||
npc.broadcastPacket(new MoveToPawn(npc, target, getDist(skill.getCastRange())));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Thread.sleep(1000);
|
||||
npc.stopMove(null);
|
||||
npc.doCast(skill);
|
||||
}
|
||||
catch (final Exception e)
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
npc.getAI().setIntention(AI_INTENTION_FOLLOW, target, null);
|
||||
}
|
||||
}
|
||||
|
||||
public int getRandomSkill(L2NpcInstance npc)
|
||||
{
|
||||
int skill;
|
||||
if (npc.getCurrentHp() > ((npc.getMaxHp() * 3) / 4))
|
||||
{
|
||||
if (Rnd.get(100) < 10)
|
||||
{
|
||||
skill = 4128;
|
||||
}
|
||||
else if (Rnd.get(100) < 10)
|
||||
{
|
||||
skill = 4129;
|
||||
}
|
||||
else
|
||||
{
|
||||
skill = 4127;
|
||||
}
|
||||
}
|
||||
else if (npc.getCurrentHp() > ((npc.getMaxHp() * 2) / 4))
|
||||
{
|
||||
if (Rnd.get(100) < 10)
|
||||
{
|
||||
skill = 4131;
|
||||
}
|
||||
else if (Rnd.get(100) < 10)
|
||||
{
|
||||
skill = 4128;
|
||||
}
|
||||
else if (Rnd.get(100) < 10)
|
||||
{
|
||||
skill = 4129;
|
||||
}
|
||||
else
|
||||
{
|
||||
skill = 4127;
|
||||
}
|
||||
}
|
||||
else if (npc.getCurrentHp() > ((npc.getMaxHp() * 1) / 4))
|
||||
{
|
||||
if (Rnd.get(100) < 10)
|
||||
{
|
||||
skill = 4130;
|
||||
}
|
||||
else if (Rnd.get(100) < 10)
|
||||
{
|
||||
skill = 4131;
|
||||
}
|
||||
else if (Rnd.get(100) < 10)
|
||||
{
|
||||
skill = 4128;
|
||||
}
|
||||
else if (Rnd.get(100) < 10)
|
||||
{
|
||||
skill = 4129;
|
||||
}
|
||||
else
|
||||
{
|
||||
skill = 4127;
|
||||
}
|
||||
}
|
||||
else if (Rnd.get(100) < 10)
|
||||
{
|
||||
skill = 4130;
|
||||
}
|
||||
else if (Rnd.get(100) < 10)
|
||||
{
|
||||
skill = 4131;
|
||||
}
|
||||
else if (Rnd.get(100) < 10)
|
||||
{
|
||||
skill = 4128;
|
||||
}
|
||||
else if (Rnd.get(100) < 10)
|
||||
{
|
||||
skill = 4129;
|
||||
}
|
||||
else
|
||||
{
|
||||
skill = 4127;
|
||||
}
|
||||
return skill;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSkillSee(L2NpcInstance npc, L2PcInstance caster, L2Skill skill, L2Object[] targets, boolean isPet)
|
||||
{
|
||||
if (npc.isInvul())
|
||||
{
|
||||
npc.getAI().setIntention(AI_INTENTION_IDLE);
|
||||
return null;
|
||||
}
|
||||
|
||||
npc.setTarget(caster);
|
||||
return super.onSkillSee(npc, caster, skill, targets, isPet);
|
||||
}
|
||||
|
||||
public int getDist(int range)
|
||||
{
|
||||
int dist = 0;
|
||||
switch (range)
|
||||
{
|
||||
case -1:
|
||||
break;
|
||||
case 100:
|
||||
dist = 85;
|
||||
break;
|
||||
default:
|
||||
dist = range - 85;
|
||||
break;
|
||||
}
|
||||
return dist;
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
// Quest class and state definition
|
||||
new Baium(-1, "baium", "ai");
|
||||
}
|
||||
}
|
222
L2J_Mobius_C4/dist/game/data/scripts/ai/individual/Core.java
vendored
Normal file
222
L2J_Mobius_C4/dist/game/data/scripts/ai/individual/Core.java
vendored
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* 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 ai.individual;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||
import com.l2jmobius.gameserver.model.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2GrandBossInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2NpcInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.quest.Quest;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.CreatureSay;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||
import com.l2jmobius.gameserver.templates.StatsSet;
|
||||
import com.l2jmobius.util.Rnd;
|
||||
|
||||
import javolution.util.FastList;
|
||||
|
||||
/**
|
||||
* Core AI
|
||||
* @author DrLecter Revised By Emperorc
|
||||
*/
|
||||
public class Core extends Quest
|
||||
{
|
||||
private static final int CORE = 12052;
|
||||
private static final int DEATH_KNIGHT = 12054;
|
||||
private static final int DEATH_WRAITH = 12055;
|
||||
private static final int SUSCEPTOR = 12058;
|
||||
|
||||
// CORE Status Tracking :
|
||||
private static final byte ALIVE = 0; // Core is spawned.
|
||||
private static final byte DEAD = 1; // Core has been killed.
|
||||
|
||||
private static boolean _FirstAttacked;
|
||||
|
||||
List<L2Attackable> Minions = new FastList<>();
|
||||
|
||||
public Core(int id, String name, String descr)
|
||||
{
|
||||
super(id, name, descr);
|
||||
|
||||
final int[] mobs =
|
||||
{
|
||||
CORE,
|
||||
DEATH_KNIGHT,
|
||||
DEATH_WRAITH,
|
||||
SUSCEPTOR
|
||||
};
|
||||
registerMobs(mobs);
|
||||
|
||||
_FirstAttacked = false;
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(CORE);
|
||||
final int status = GrandBossManager.getInstance().getBossStatus(CORE);
|
||||
if (status == DEAD)
|
||||
{
|
||||
// load the unlock date and time for Core from DB
|
||||
final long temp = (info.getLong("respawn_time") - System.currentTimeMillis());
|
||||
// if Core is locked until a certain time, mark it so and start the unlock timer
|
||||
// the unlock time has not yet expired.
|
||||
if (temp > 0)
|
||||
{
|
||||
startQuestTimer("core_unlock", temp, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// the time has already expired while the server was offline. Immediately spawn Core.
|
||||
final L2GrandBossInstance core = (L2GrandBossInstance) addSpawn(CORE, 17726, 108915, -6490, 0, false, 0);
|
||||
GrandBossManager.getInstance().setBossStatus(CORE, ALIVE);
|
||||
spawnBoss(core);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
final String test = loadGlobalQuestVar("Core_Attacked");
|
||||
if (test.equalsIgnoreCase("true"))
|
||||
{
|
||||
_FirstAttacked = true;
|
||||
}
|
||||
final int loc_x = info.getInteger("loc_x");
|
||||
final int loc_y = info.getInteger("loc_y");
|
||||
final int loc_z = info.getInteger("loc_z");
|
||||
final int heading = info.getInteger("heading");
|
||||
final int hp = info.getInteger("currentHP");
|
||||
final int mp = info.getInteger("currentMP");
|
||||
final L2GrandBossInstance core = (L2GrandBossInstance) addSpawn(CORE, loc_x, loc_y, loc_z, heading, false, 0);
|
||||
core.setCurrentHpMp(hp, mp);
|
||||
spawnBoss(core);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveGlobalData()
|
||||
{
|
||||
final String val = "" + _FirstAttacked;
|
||||
saveGlobalQuestVar("Core_Attacked", val);
|
||||
}
|
||||
|
||||
public void spawnBoss(L2GrandBossInstance npc)
|
||||
{
|
||||
GrandBossManager.getInstance().addBoss(npc);
|
||||
npc.broadcastPacket(new PlaySound(1, "BS01_A", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
|
||||
|
||||
// Spawn minions
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
final int x = 16800 + (i * 360);
|
||||
Minions.add((L2Attackable) addSpawn(DEATH_KNIGHT, x, 110000, npc.getZ(), 280 + Rnd.get(40), false, 0));
|
||||
Minions.add((L2Attackable) addSpawn(DEATH_KNIGHT, x, 109000, npc.getZ(), 280 + Rnd.get(40), false, 0));
|
||||
final int x2 = 16800 + (i * 600);
|
||||
Minions.add((L2Attackable) addSpawn(DEATH_WRAITH, x2, 109300, npc.getZ(), 280 + Rnd.get(40), false, 0));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
final int x = 16800 + (i * 450);
|
||||
Minions.add((L2Attackable) addSpawn(SUSCEPTOR, x, 110300, npc.getZ(), 280 + Rnd.get(40), false, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2NpcInstance npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equalsIgnoreCase("core_unlock"))
|
||||
{
|
||||
final L2GrandBossInstance core = (L2GrandBossInstance) addSpawn(CORE, 17726, 108915, -6490, 0, false, 0);
|
||||
GrandBossManager.getInstance().setBossStatus(CORE, ALIVE);
|
||||
spawnBoss(core);
|
||||
}
|
||||
else if (event.equalsIgnoreCase("spawn_minion"))
|
||||
{
|
||||
Minions.add((L2Attackable) addSpawn(npc.getNpcId(), npc.getX(), npc.getY(), npc.getZ(), npc.getHeading(), false, 0));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("despawn_minions"))
|
||||
{
|
||||
for (int i = 0; i < Minions.size(); i++)
|
||||
{
|
||||
final L2Attackable mob = Minions.get(i);
|
||||
if (mob != null)
|
||||
{
|
||||
mob.decayMe();
|
||||
}
|
||||
}
|
||||
Minions.clear();
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2NpcInstance npc, L2PcInstance attacker, int damage, boolean isPet)
|
||||
{
|
||||
if (npc.getNpcId() == CORE)
|
||||
{
|
||||
if (_FirstAttacked)
|
||||
{
|
||||
if (Rnd.get(100) == 0)
|
||||
{
|
||||
npc.broadcastPacket(new CreatureSay(npc.getObjectId(), 0, npc.getName(), "Removing intruders."));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_FirstAttacked = true;
|
||||
npc.broadcastPacket(new CreatureSay(npc.getObjectId(), 0, npc.getName(), "A non-permitted target has been discovered."));
|
||||
npc.broadcastPacket(new CreatureSay(npc.getObjectId(), 0, npc.getName(), "Starting intruder removal system."));
|
||||
}
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isPet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2NpcInstance npc, L2PcInstance killer, boolean isPet)
|
||||
{
|
||||
if (npc.getNpcId() == CORE)
|
||||
{
|
||||
final int objId = npc.getObjectId();
|
||||
npc.broadcastPacket(new PlaySound(1, "BS02_D", 1, objId, npc.getX(), npc.getY(), npc.getZ()));
|
||||
npc.broadcastPacket(new CreatureSay(objId, 0, npc.getName(), "A fatal error has occurred."));
|
||||
npc.broadcastPacket(new CreatureSay(objId, 0, npc.getName(), "System is being shut down..."));
|
||||
npc.broadcastPacket(new CreatureSay(objId, 0, npc.getName(), "......"));
|
||||
_FirstAttacked = false;
|
||||
addSpawn(12053, 16502, 110165, -6394, 0, false, 900000);
|
||||
addSpawn(12053, 18948, 110166, -6397, 0, false, 900000);
|
||||
GrandBossManager.getInstance().setBossStatus(CORE, DEAD);
|
||||
// time is 60hour +/- 23hour
|
||||
final long respawnTime = (27 + Rnd.get(47)) * 3600000;
|
||||
startQuestTimer("core_unlock", respawnTime, null, null);
|
||||
// also save the respawn time so that the info is maintained past reboots
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(CORE);
|
||||
info.set("respawn_time", (System.currentTimeMillis() + respawnTime));
|
||||
GrandBossManager.getInstance().setStatsSet(CORE, info);
|
||||
startQuestTimer("despawn_minions", 20000, null, null);
|
||||
cancelQuestTimers("spawn_minion");
|
||||
}
|
||||
else if ((GrandBossManager.getInstance().getBossStatus(CORE) == ALIVE) && (Minions != null) && Minions.contains(npc))
|
||||
{
|
||||
Minions.remove(npc);
|
||||
startQuestTimer("spawn_minion", 60000, npc, null);
|
||||
}
|
||||
return super.onKill(npc, killer, isPet);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
// now call the constructor (starts up the ai)
|
||||
new Core(-1, "core", "ai");
|
||||
}
|
||||
}
|
73
L2J_Mobius_C4/dist/game/data/scripts/ai/individual/Elpy.java
vendored
Normal file
73
L2J_Mobius_C4/dist/game/data/scripts/ai/individual/Elpy.java
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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 ai.individual;
|
||||
|
||||
import com.l2jmobius.gameserver.GeoData;
|
||||
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
||||
import com.l2jmobius.gameserver.model.L2CharPosition;
|
||||
import com.l2jmobius.gameserver.model.L2Character;
|
||||
import com.l2jmobius.gameserver.model.L2Summon;
|
||||
import com.l2jmobius.gameserver.model.Location;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2NpcInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.quest.Quest;
|
||||
import com.l2jmobius.gameserver.util.Util;
|
||||
|
||||
/**
|
||||
* @author Mobius
|
||||
*/
|
||||
public class Elpy extends Quest
|
||||
{
|
||||
// NPCs
|
||||
private static final int[] MOBS =
|
||||
{
|
||||
432, // Elpy
|
||||
};
|
||||
// Misc
|
||||
private static final int FLEE_DISTANCE = 500;
|
||||
|
||||
public Elpy(int questId, String name, String descr)
|
||||
{
|
||||
super(questId, name, descr);
|
||||
registerMobs(MOBS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2NpcInstance npc, L2PcInstance attacker, int damage, boolean isPet)
|
||||
{
|
||||
npc.disableCoreAI(true);
|
||||
npc.setRunning();
|
||||
|
||||
final L2Summon summon = isPet ? attacker.getPet() : null;
|
||||
final L2Character actualAttacker = summon == null ? attacker : summon;
|
||||
final double radians = Math.toRadians(Util.calculateAngleFrom(actualAttacker, npc));
|
||||
final int posX = (int) (npc.getX() + (FLEE_DISTANCE * Math.cos(radians)));
|
||||
final int posY = (int) (npc.getY() + (FLEE_DISTANCE * Math.sin(radians)));
|
||||
final int posZ = npc.getZ();
|
||||
|
||||
final Location destination = GeoData.getInstance().moveCheck(npc.getX(), npc.getY(), npc.getZ(), posX, posY, posZ);
|
||||
final L2CharPosition charPos = new L2CharPosition(destination.getX(), destination.getY(), destination.getZ(), destination.getHeading());
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, charPos);
|
||||
return super.onAttack(npc, attacker, damage, isPet);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
// now call the constructor (starts up the ai)
|
||||
new Elpy(-1, "eply", "ai");
|
||||
}
|
||||
}
|
84
L2J_Mobius_C4/dist/game/data/scripts/ai/individual/HoneyBear.java
vendored
Normal file
84
L2J_Mobius_C4/dist/game/data/scripts/ai/individual/HoneyBear.java
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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 ai.individual;
|
||||
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2NpcInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.quest.Quest;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.CreatureSay;
|
||||
import com.l2jmobius.util.Rnd;
|
||||
|
||||
/**
|
||||
* @by Karakan for L2JLisvus
|
||||
*/
|
||||
public class HoneyBear extends Quest
|
||||
{
|
||||
private static final int HONEY_BEAR = 5058;
|
||||
|
||||
public HoneyBear(int questId, String name, String descr)
|
||||
{
|
||||
super(questId, name, descr);
|
||||
final int[] mobs =
|
||||
{
|
||||
HONEY_BEAR
|
||||
};
|
||||
registerMobs(mobs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2NpcInstance npc)
|
||||
{
|
||||
if ((npc.getNpcId() == HONEY_BEAR) && (Rnd.get(10) == 0))
|
||||
{
|
||||
npc.broadcastPacket(new CreatureSay(npc.getObjectId(), 1, npc.getName(), "What does honey of this place taste like?!"));
|
||||
}
|
||||
else
|
||||
{
|
||||
npc.broadcastPacket(new CreatureSay(npc.getObjectId(), 1, npc.getName(), "Give me some sweet, delicious golden honey!"));
|
||||
}
|
||||
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2NpcInstance npc, L2PcInstance attacker, int damage, boolean isPet)
|
||||
{
|
||||
if ((npc.getCurrentHp() / npc.getMaxHp()) > 0.99)
|
||||
{
|
||||
npc.broadcastPacket(new CreatureSay(npc.getObjectId(), 1, npc.getName(), "If you give me some honey, I'll at least spare your life..."));
|
||||
}
|
||||
|
||||
return super.onAttack(npc, attacker, damage, isPet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2NpcInstance npc, L2PcInstance killer, boolean isPet)
|
||||
{
|
||||
if (npc.getNpcId() == HONEY_BEAR)
|
||||
{
|
||||
npc.broadcastPacket(new CreatureSay(npc.getObjectId(), 1, npc.getName(), "Only for lack of honey did I lose to the likes of you."));
|
||||
}
|
||||
|
||||
return super.onKill(npc, killer, isPet);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
// now call the constructor (starts up the ai)
|
||||
new HoneyBear(-1, "honeybear", "ai");
|
||||
}
|
||||
}
|
374
L2J_Mobius_C4/dist/game/data/scripts/ai/individual/Orfen.java
vendored
Normal file
374
L2J_Mobius_C4/dist/game/data/scripts/ai/individual/Orfen.java
vendored
Normal file
@@ -0,0 +1,374 @@
|
||||
/*
|
||||
* 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 ai.individual;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
||||
import com.l2jmobius.gameserver.datatables.SkillTable;
|
||||
import com.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||
import com.l2jmobius.gameserver.model.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.L2Character;
|
||||
import com.l2jmobius.gameserver.model.L2Object;
|
||||
import com.l2jmobius.gameserver.model.L2Skill;
|
||||
import com.l2jmobius.gameserver.model.L2Spawn;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2GrandBossInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2NpcInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.quest.Quest;
|
||||
import com.l2jmobius.gameserver.model.zone.type.L2BossZone;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.CreatureSay;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||
import com.l2jmobius.gameserver.templates.StatsSet;
|
||||
import com.l2jmobius.util.Rnd;
|
||||
|
||||
import javolution.util.FastList;
|
||||
|
||||
/**
|
||||
* Orfen AI
|
||||
* @author Emperorc
|
||||
*/
|
||||
public class Orfen extends Quest
|
||||
{
|
||||
private static final int[][] Pos =
|
||||
{
|
||||
{
|
||||
43728,
|
||||
17220,
|
||||
-4342
|
||||
},
|
||||
{
|
||||
55024,
|
||||
17368,
|
||||
-5412
|
||||
},
|
||||
{
|
||||
53504,
|
||||
21248,
|
||||
-5486
|
||||
},
|
||||
{
|
||||
53248,
|
||||
24576,
|
||||
-5262
|
||||
}
|
||||
};
|
||||
|
||||
private static final String[] Text =
|
||||
{
|
||||
"PLAYERNAME. Stop kidding yourself about your own powerlessness!",
|
||||
"PLAYERNAME. I'll make you feel what true fear is!",
|
||||
"You're really stupid to have challenged me. PLAYERNAME! Get ready!",
|
||||
"PLAYERNAME. Do you think that's going to work?!"
|
||||
};
|
||||
|
||||
private static final int ORFEN = 12169;
|
||||
private static final int RAIKEL_LEOS = 12171;
|
||||
private static final int RIBA_IREN = 12173;
|
||||
|
||||
private static boolean _IsTeleported;
|
||||
private static List<L2Attackable> _Minions = new FastList<>();
|
||||
private static L2BossZone _Zone;
|
||||
|
||||
private static final byte ALIVE = 0;
|
||||
private static final byte DEAD = 1;
|
||||
|
||||
public Orfen(int id, String name, String descr)
|
||||
{
|
||||
super(id, name, descr);
|
||||
final int[] mobs =
|
||||
{
|
||||
ORFEN,
|
||||
RAIKEL_LEOS,
|
||||
RIBA_IREN
|
||||
};
|
||||
registerMobs(mobs);
|
||||
_IsTeleported = false;
|
||||
_Zone = GrandBossManager.getInstance().getZone(Pos[0][0], Pos[0][1], Pos[0][2]);
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(ORFEN);
|
||||
final int status = GrandBossManager.getInstance().getBossStatus(ORFEN);
|
||||
if (status == DEAD)
|
||||
{
|
||||
// load the unlock date and time for Orfen from DB
|
||||
final long temp = info.getLong("respawn_time") - System.currentTimeMillis();
|
||||
// if Orfen is locked until a certain time, mark it so and start the unlock timer
|
||||
// the unlock time has not yet expired.
|
||||
if (temp > 0)
|
||||
{
|
||||
startQuestTimer("orfen_unlock", temp, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// the time has already expired while the server was offline. Immediately spawn Orfen.
|
||||
final int i = Rnd.get(10);
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int z = 0;
|
||||
if (i < 4)
|
||||
{
|
||||
x = Pos[1][0];
|
||||
y = Pos[1][1];
|
||||
z = Pos[1][2];
|
||||
}
|
||||
else if (i < 7)
|
||||
{
|
||||
x = Pos[2][0];
|
||||
y = Pos[2][1];
|
||||
z = Pos[2][2];
|
||||
}
|
||||
else
|
||||
{
|
||||
x = Pos[3][0];
|
||||
y = Pos[3][1];
|
||||
z = Pos[3][2];
|
||||
}
|
||||
|
||||
final L2GrandBossInstance orfen = (L2GrandBossInstance) addSpawn(ORFEN, x, y, z, 0, false, 0);
|
||||
GrandBossManager.getInstance().setBossStatus(ORFEN, ALIVE);
|
||||
spawnBoss(orfen);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
final int loc_x = info.getInteger("loc_x");
|
||||
final int loc_y = info.getInteger("loc_y");
|
||||
final int loc_z = info.getInteger("loc_z");
|
||||
final int heading = info.getInteger("heading");
|
||||
final int hp = info.getInteger("currentHP");
|
||||
final int mp = info.getInteger("currentMP");
|
||||
final L2GrandBossInstance orfen = (L2GrandBossInstance) addSpawn(ORFEN, loc_x, loc_y, loc_z, heading, false, 0);
|
||||
orfen.setCurrentHpMp(hp, mp);
|
||||
spawnBoss(orfen);
|
||||
}
|
||||
}
|
||||
|
||||
public void setSpawnPoint(L2NpcInstance npc, int index)
|
||||
{
|
||||
((L2Attackable) npc).clearAggroList();
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE, null, null);
|
||||
final L2Spawn spawn = npc.getSpawn();
|
||||
spawn.setLocx(Pos[index][0]);
|
||||
spawn.setLocy(Pos[index][1]);
|
||||
spawn.setLocz(Pos[index][2]);
|
||||
npc.teleToLocation(Pos[index][0], Pos[index][1], Pos[index][2]);
|
||||
}
|
||||
|
||||
public void spawnBoss(L2GrandBossInstance npc)
|
||||
{
|
||||
GrandBossManager.getInstance().addBoss(npc);
|
||||
npc.broadcastPacket(new PlaySound(1, "BS01_A", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
|
||||
startQuestTimer("check_orfen_pos", 10000, npc, null, true);
|
||||
|
||||
// Spawn minions
|
||||
final int x = npc.getX();
|
||||
final int y = npc.getY();
|
||||
_Minions.add((L2Attackable) addSpawn(RAIKEL_LEOS, x + 100, y + 100, npc.getZ(), 0, false, 0));
|
||||
_Minions.add((L2Attackable) addSpawn(RAIKEL_LEOS, x + 100, y - 100, npc.getZ(), 0, false, 0));
|
||||
_Minions.add((L2Attackable) addSpawn(RAIKEL_LEOS, x - 100, y + 100, npc.getZ(), 0, false, 0));
|
||||
_Minions.add((L2Attackable) addSpawn(RAIKEL_LEOS, x - 100, y - 100, npc.getZ(), 0, false, 0));
|
||||
startQuestTimer("check_minion_loc", 10000, npc, null, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2NpcInstance npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equalsIgnoreCase("orfen_unlock"))
|
||||
{
|
||||
final int i = Rnd.get(10);
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int z = 0;
|
||||
if (i < 4)
|
||||
{
|
||||
x = Pos[1][0];
|
||||
y = Pos[1][1];
|
||||
z = Pos[1][2];
|
||||
}
|
||||
else if (i < 7)
|
||||
{
|
||||
x = Pos[2][0];
|
||||
y = Pos[2][1];
|
||||
z = Pos[2][2];
|
||||
}
|
||||
else
|
||||
{
|
||||
x = Pos[3][0];
|
||||
y = Pos[3][1];
|
||||
z = Pos[3][2];
|
||||
}
|
||||
|
||||
final L2GrandBossInstance orfen = (L2GrandBossInstance) addSpawn(ORFEN, x, y, z, 0, false, 0);
|
||||
GrandBossManager.getInstance().setBossStatus(ORFEN, ALIVE);
|
||||
spawnBoss(orfen);
|
||||
}
|
||||
else if (event.equalsIgnoreCase("check_orfen_pos"))
|
||||
{
|
||||
if ((_IsTeleported && (npc.getCurrentHp() > (npc.getMaxHp() * 0.95))) || (!_Zone.isInsideZone(npc) && !_IsTeleported))
|
||||
{
|
||||
setSpawnPoint(npc, Rnd.get(3) + 1);
|
||||
_IsTeleported = false;
|
||||
}
|
||||
else if (_IsTeleported && !_Zone.isInsideZone(npc))
|
||||
{
|
||||
setSpawnPoint(npc, 0);
|
||||
}
|
||||
}
|
||||
else if (event.equalsIgnoreCase("check_minion_loc"))
|
||||
{
|
||||
for (int i = 0; i < _Minions.size(); i++)
|
||||
{
|
||||
final L2Attackable mob = _Minions.get(i);
|
||||
if (!npc.isInsideRadius(mob, 3000, false, false))
|
||||
{
|
||||
mob.teleToLocation(npc.getX(), npc.getY(), npc.getZ());
|
||||
((L2Attackable) npc).clearAggroList();
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event.equalsIgnoreCase("despawn_minions"))
|
||||
{
|
||||
for (int i = 0; i < _Minions.size(); i++)
|
||||
{
|
||||
final L2Attackable mob = _Minions.get(i);
|
||||
if (mob != null)
|
||||
{
|
||||
mob.decayMe();
|
||||
}
|
||||
}
|
||||
_Minions.clear();
|
||||
}
|
||||
else if (event.equalsIgnoreCase("spawn_minion"))
|
||||
{
|
||||
_Minions.add((L2Attackable) addSpawn(RAIKEL_LEOS, npc.getX(), npc.getY(), npc.getZ(), 0, false, 0));
|
||||
}
|
||||
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSkillSee(L2NpcInstance npc, L2PcInstance caster, L2Skill skill, L2Object[] targets, boolean isPet)
|
||||
{
|
||||
if (npc.getNpcId() == ORFEN)
|
||||
{
|
||||
final L2Character originalCaster = isPet ? caster.getPet() : caster;
|
||||
if (skill.hasAggro() && (Rnd.get(5) == 0) && npc.isInsideRadius(originalCaster, 1000, false, false))
|
||||
{
|
||||
npc.broadcastPacket(new CreatureSay(npc.getObjectId(), 0, npc.getName(), Text[Rnd.get(4)].replace("PLAYERNAME", caster.getName().toString())));
|
||||
originalCaster.teleToLocation(npc.getX(), npc.getY(), npc.getZ());
|
||||
npc.setTarget(originalCaster);
|
||||
npc.doCast(SkillTable.getInstance().getInfo(4064, 1));
|
||||
}
|
||||
}
|
||||
return super.onSkillSee(npc, caster, skill, targets, isPet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onFactionCall(L2NpcInstance npc, L2NpcInstance caller, L2PcInstance attacker, boolean isPet)
|
||||
{
|
||||
if ((caller == null) || (npc == null))
|
||||
{
|
||||
return super.onFactionCall(npc, caller, attacker, isPet);
|
||||
}
|
||||
|
||||
final int npcId = npc.getNpcId();
|
||||
final int callerId = caller.getNpcId();
|
||||
if ((npcId == RAIKEL_LEOS) && (Rnd.get(20) == 0))
|
||||
{
|
||||
npc.setTarget(attacker);
|
||||
npc.doCast(SkillTable.getInstance().getInfo(4067, 4));
|
||||
}
|
||||
else if (npcId == RIBA_IREN)
|
||||
{
|
||||
int chance = 1;
|
||||
if (callerId == ORFEN)
|
||||
{
|
||||
chance = 9;
|
||||
}
|
||||
if ((callerId != RIBA_IREN) && (caller.getCurrentHp() < (caller.getMaxHp() / 2)) && (Rnd.get(10) < chance))
|
||||
{
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE, null, null);
|
||||
npc.setTarget(caller);
|
||||
npc.doCast(SkillTable.getInstance().getInfo(4516, 1));
|
||||
}
|
||||
}
|
||||
return super.onFactionCall(npc, caller, attacker, isPet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2NpcInstance npc, L2PcInstance attacker, int damage, boolean isPet)
|
||||
{
|
||||
final int npcId = npc.getNpcId();
|
||||
if (npcId == ORFEN)
|
||||
{
|
||||
if (((npc.getCurrentHp() - damage) < (npc.getMaxHp() / 2)) && !_IsTeleported)
|
||||
{
|
||||
setSpawnPoint(npc, 0);
|
||||
_IsTeleported = true;
|
||||
}
|
||||
else if (npc.isInsideRadius(attacker, 1000, false, false) && !npc.isInsideRadius(attacker, 300, false, false) && (Rnd.get(10) == 0))
|
||||
{
|
||||
npc.broadcastPacket(new CreatureSay(npc.getObjectId(), 0, npc.getName(), Text[Rnd.get(3)].replace("PLAYERNAME", attacker.getName().toString())));
|
||||
attacker.teleToLocation(npc.getX(), npc.getY(), npc.getZ());
|
||||
npc.setTarget(attacker);
|
||||
npc.doCast(SkillTable.getInstance().getInfo(4064, 1));
|
||||
}
|
||||
}
|
||||
else if (npcId == RIBA_IREN)
|
||||
{
|
||||
if ((npc.getCurrentHp() - damage) < (npc.getMaxHp() / 2))
|
||||
{
|
||||
npc.setTarget(attacker);
|
||||
npc.doCast(SkillTable.getInstance().getInfo(4516, 1));
|
||||
}
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isPet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2NpcInstance npc, L2PcInstance killer, boolean isPet)
|
||||
{
|
||||
if (npc.getNpcId() == ORFEN)
|
||||
{
|
||||
npc.broadcastPacket(new PlaySound(1, "BS02_D", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
|
||||
GrandBossManager.getInstance().setBossStatus(ORFEN, DEAD);
|
||||
// time is 48hour +/- 20hour
|
||||
final long respawnTime = (28 + (Rnd.get(41) * 3600000));
|
||||
startQuestTimer("orfen_unlock", respawnTime, null, null);
|
||||
// also save the respawn time so that the info is maintained past reboots
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(ORFEN);
|
||||
info.set("respawn_time", System.currentTimeMillis() + respawnTime);
|
||||
GrandBossManager.getInstance().setStatsSet(ORFEN, info);
|
||||
cancelQuestTimer("check_minion_loc", npc, null);
|
||||
cancelQuestTimer("check_orfen_pos", npc, null);
|
||||
startQuestTimer("despawn_minions", 20000, null, null);
|
||||
cancelQuestTimers("spawn_minion");
|
||||
}
|
||||
else if ((GrandBossManager.getInstance().getBossStatus(ORFEN) == ALIVE) && (npc.getNpcId() == RAIKEL_LEOS))
|
||||
{
|
||||
_Minions.remove(npc);
|
||||
startQuestTimer("spawn_minion", 360000, npc, null);
|
||||
}
|
||||
return super.onKill(npc, killer, isPet);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
// Quest class and state definition
|
||||
new Orfen(-1, "orfen", "ai");
|
||||
}
|
||||
}
|
289
L2J_Mobius_C4/dist/game/data/scripts/ai/individual/QueenAnt.java
vendored
Normal file
289
L2J_Mobius_C4/dist/game/data/scripts/ai/individual/QueenAnt.java
vendored
Normal file
@@ -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 ai.individual;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
||||
import com.l2jmobius.gameserver.datatables.SkillTable;
|
||||
import com.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||
import com.l2jmobius.gameserver.model.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2GrandBossInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2NpcInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.quest.Quest;
|
||||
import com.l2jmobius.gameserver.model.zone.type.L2BossZone;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.SocialAction;
|
||||
import com.l2jmobius.gameserver.templates.StatsSet;
|
||||
import com.l2jmobius.util.Rnd;
|
||||
|
||||
import javolution.util.FastList;
|
||||
|
||||
/**
|
||||
* Queen Ant AI
|
||||
* @author Emperorc
|
||||
*/
|
||||
public class QueenAnt extends Quest
|
||||
{
|
||||
private static final int QUEEN = 12001;
|
||||
private static final int LARVA = 12002;
|
||||
private static final int NURSE = 12003;
|
||||
private static final int GUARD = 12004;
|
||||
private static final int ROYAL = 12005;
|
||||
|
||||
// QUEEN Status Tracking :
|
||||
private static final byte ALIVE = 0; // Queen Ant is spawned.
|
||||
private static final byte DEAD = 1; // Queen Ant has been killed.
|
||||
|
||||
private static L2BossZone _Zone;
|
||||
private static List<L2Attackable> _Minions = new FastList<>();
|
||||
|
||||
public QueenAnt(int questId, String name, String descr)
|
||||
{
|
||||
super(questId, name, descr);
|
||||
final int[] mobs =
|
||||
{
|
||||
QUEEN,
|
||||
LARVA,
|
||||
NURSE,
|
||||
GUARD,
|
||||
ROYAL
|
||||
};
|
||||
registerMobs(mobs);
|
||||
_Zone = GrandBossManager.getInstance().getZone(-21610, 181594, -5734);
|
||||
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(QUEEN);
|
||||
final int status = GrandBossManager.getInstance().getBossStatus(QUEEN);
|
||||
if (status == DEAD)
|
||||
{
|
||||
// load the unlock date and time for queen ant from DB
|
||||
final long temp = info.getLong("respawn_time") - System.currentTimeMillis();
|
||||
// if queen ant is locked until a certain time, mark it so and start the unlock timer
|
||||
// the unlock time has not yet expired.
|
||||
if (temp > 0)
|
||||
{
|
||||
startQuestTimer("queen_unlock", temp, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// the time has already expired while the server was offline. Immediately spawn queen ant.
|
||||
final L2GrandBossInstance queen = (L2GrandBossInstance) addSpawn(QUEEN, -21610, 181594, -5734, 0, false, 0);
|
||||
GrandBossManager.getInstance().setBossStatus(QUEEN, ALIVE);
|
||||
spawnBoss(queen);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
final int loc_x = info.getInteger("loc_x");
|
||||
final int loc_y = info.getInteger("loc_y");
|
||||
final int loc_z = info.getInteger("loc_z");
|
||||
final int heading = info.getInteger("heading");
|
||||
final int hp = info.getInteger("currentHP");
|
||||
final int mp = info.getInteger("currentMP");
|
||||
final L2GrandBossInstance queen = (L2GrandBossInstance) addSpawn(QUEEN, loc_x, loc_y, loc_z, heading, false, 0);
|
||||
queen.setCurrentHpMp(hp, mp);
|
||||
spawnBoss(queen);
|
||||
}
|
||||
}
|
||||
|
||||
public void spawnBoss(L2GrandBossInstance npc)
|
||||
{
|
||||
GrandBossManager.getInstance().addBoss(npc);
|
||||
if (Rnd.get(100) < 33)
|
||||
{
|
||||
_Zone.movePlayersTo(-19480, 187344, -5600);
|
||||
}
|
||||
else if (Rnd.get(100) < 50)
|
||||
{
|
||||
_Zone.movePlayersTo(-17928, 180912, -5520);
|
||||
}
|
||||
else
|
||||
{
|
||||
_Zone.movePlayersTo(-23808, 182368, -5600);
|
||||
}
|
||||
GrandBossManager.getInstance().addBoss(npc);
|
||||
startQuestTimer("action", 10000, npc, null, true);
|
||||
npc.broadcastPacket(new PlaySound(1, "BS02_D", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
|
||||
// Spawn minions
|
||||
addSpawn(LARVA, -21600, 179482, -5846, Rnd.get(360), false, 0);
|
||||
addSpawn(NURSE, -22000, 179482, -5846, 0, false, 0);
|
||||
addSpawn(NURSE, -21200, 179482, -5846, 0, false, 0);
|
||||
|
||||
final int radius = 400;
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
final int x = (int) (radius * Math.cos(i * 1.407)); // 1.407~2pi/6
|
||||
final int y = (int) (radius * Math.sin(i * 1.407));
|
||||
addSpawn(NURSE, npc.getX() + x, npc.getY() + y, npc.getZ(), 0, false, 0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
final int x = (int) (radius * Math.cos(i * .7854)); // .7854~2pi/8
|
||||
final int y = (int) (radius * Math.sin(i * .7854));
|
||||
_Minions.add((L2Attackable) addSpawn(ROYAL, npc.getX() + x, npc.getY() + y, npc.getZ(), 0, false, 0));
|
||||
}
|
||||
startQuestTimer("check_royal__Zone", 120000, npc, null, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2NpcInstance npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equalsIgnoreCase("action") && (npc != null))
|
||||
{
|
||||
if (Rnd.get(3) == 0)
|
||||
{
|
||||
if (Rnd.get(2) == 0)
|
||||
{
|
||||
npc.broadcastPacket(new SocialAction(npc.getObjectId(), 3));
|
||||
}
|
||||
else
|
||||
{
|
||||
npc.broadcastPacket(new SocialAction(npc.getObjectId(), 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event.equalsIgnoreCase("queen_unlock"))
|
||||
{
|
||||
final L2GrandBossInstance queen = (L2GrandBossInstance) addSpawn(QUEEN, -21610, 181594, -5734, 0, false, 0);
|
||||
GrandBossManager.getInstance().setBossStatus(QUEEN, ALIVE);
|
||||
spawnBoss(queen);
|
||||
}
|
||||
else if (event.equalsIgnoreCase("check_royal__Zone") && (npc != null))
|
||||
{
|
||||
for (int i = 0; i < _Minions.size(); i++)
|
||||
{
|
||||
final L2Attackable mob = _Minions.get(i);
|
||||
if ((mob != null) && !_Zone.isInsideZone(mob))
|
||||
{
|
||||
mob.teleToLocation(npc.getX(), npc.getY(), npc.getZ());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event.equalsIgnoreCase("despawn_royals"))
|
||||
{
|
||||
for (int i = 0; i < _Minions.size(); i++)
|
||||
{
|
||||
final L2Attackable mob = _Minions.get(i);
|
||||
if (mob != null)
|
||||
{
|
||||
mob.decayMe();
|
||||
}
|
||||
}
|
||||
_Minions.clear();
|
||||
}
|
||||
else if (event.equalsIgnoreCase("spawn_royal"))
|
||||
{
|
||||
_Minions.add((L2Attackable) addSpawn(ROYAL, npc.getX(), npc.getY(), npc.getZ(), 0, false, 0));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("spawn_nurse"))
|
||||
{
|
||||
addSpawn(NURSE, npc.getX(), npc.getY(), npc.getZ(), 0, false, 0);
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onFactionCall(L2NpcInstance npc, L2NpcInstance caller, L2PcInstance attacker, boolean isPet)
|
||||
{
|
||||
if ((caller == null) || (npc == null))
|
||||
{
|
||||
return super.onFactionCall(npc, caller, attacker, isPet);
|
||||
}
|
||||
|
||||
final int npcId = npc.getNpcId();
|
||||
final int callerId = caller.getNpcId();
|
||||
if (npcId == NURSE)
|
||||
{
|
||||
if (callerId == LARVA)
|
||||
{
|
||||
npc.setTarget(caller);
|
||||
npc.doCast(SkillTable.getInstance().getInfo(4020, 1));
|
||||
npc.doCast(SkillTable.getInstance().getInfo(4024, 1));
|
||||
return null;
|
||||
}
|
||||
else if (callerId == QUEEN)
|
||||
{
|
||||
if ((npc.getTarget() != null) && (npc.getTarget() instanceof L2NpcInstance))
|
||||
{
|
||||
if (((L2NpcInstance) npc.getTarget()).getNpcId() == LARVA)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
npc.setTarget(caller);
|
||||
npc.doCast(SkillTable.getInstance().getInfo(4020, 1));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return super.onFactionCall(npc, caller, attacker, isPet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2NpcInstance npc, L2PcInstance attacker, int damage, boolean isPet)
|
||||
{
|
||||
final int npcId = npc.getNpcId();
|
||||
if (npcId == NURSE)
|
||||
{
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE, null, null);
|
||||
return null;
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isPet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2NpcInstance npc, L2PcInstance killer, boolean isPet)
|
||||
{
|
||||
final int npcId = npc.getNpcId();
|
||||
if (npcId == QUEEN)
|
||||
{
|
||||
npc.broadcastPacket(new PlaySound(1, "BS02_D", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
|
||||
GrandBossManager.getInstance().setBossStatus(QUEEN, DEAD);
|
||||
// time is 36hour +/- 17hour
|
||||
final long respawnTime = ((19 + Rnd.get(35)) * 3600000);
|
||||
startQuestTimer("queen_unlock", respawnTime, null, null);
|
||||
cancelQuestTimer("action", npc, null);
|
||||
// also save the respawn time so that the info is maintained past reboots
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(QUEEN);
|
||||
info.set("respawn_time", System.currentTimeMillis() + respawnTime);
|
||||
GrandBossManager.getInstance().setStatsSet(QUEEN, info);
|
||||
startQuestTimer("despawn_royals", 20000, null, null);
|
||||
cancelQuestTimers("spawn_minion");
|
||||
}
|
||||
else if (GrandBossManager.getInstance().getBossStatus(QUEEN) == ALIVE)
|
||||
{
|
||||
if (npcId == ROYAL)
|
||||
{
|
||||
_Minions.remove(npc);
|
||||
startQuestTimer("spawn_royal", (280 + Rnd.get(40)) * 1000, npc, null);
|
||||
}
|
||||
else if (npcId == NURSE)
|
||||
{
|
||||
startQuestTimer("spawn_nurse", 10000, npc, null);
|
||||
}
|
||||
}
|
||||
return super.onKill(npc, killer, isPet);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
// now call the constructor (starts up the ai)
|
||||
new QueenAnt(-1, "queen_ant", "ai");
|
||||
}
|
||||
}
|
1968
L2J_Mobius_C4/dist/game/data/scripts/ai/individual/Valakas.java
vendored
Normal file
1968
L2J_Mobius_C4/dist/game/data/scripts/ai/individual/Valakas.java
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1093
L2J_Mobius_C4/dist/game/data/scripts/ai/individual/Zaken.java
vendored
Normal file
1093
L2J_Mobius_C4/dist/game/data/scripts/ai/individual/Zaken.java
vendored
Normal file
File diff suppressed because it is too large
Load Diff
13
L2J_Mobius_C4/dist/game/data/scripts/ai/individual/documentation.txt
vendored
Normal file
13
L2J_Mobius_C4/dist/game/data/scripts/ai/individual/documentation.txt
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
Individual AI:
|
||||
This folder contains AI scripts for single npc templates (one npc ID, but possibly many instances).
|
||||
That is, if a particular NPC/mob has a unique AI or something slightly different from all other generic NPCs,
|
||||
an individual AI script can be created for all occurences of that npc/mob. Such individual scripts ought to be here.
|
||||
|
||||
Individual AI scripts can be subclassed. In other words, an individual may inherit from a group or other individual.
|
||||
For example, one group template might define mobs that cast spells. A particular mob may cast spells but may also
|
||||
talk whenever it gets attacked. In that case, instead of writing all the AI for attacking and casting spells, it may
|
||||
inherit from a group template that defines AI for ALL mobs that cast spells, then add behaviours for talking onAttack.
|
||||
|
||||
"NPC registrations" refers to the addition of NPCs in the various events of the scripts, such as onAttack, onKill, etc
|
||||
Those are done by using keywords such as "addKillId" etc. For more details on registrations, see
|
||||
"scripts/quests/documentation.txt"
|
Reference in New Issue
Block a user