ArcEmu: Basic Npc Script - ArcEmu

Jump to content

Toggle shoutbox Lastest Announcements

dfighter  : (07 December 2014 - 12:06 PM) Arcemu is in hibernation mode, please read http://arcemu.org/fo...showtopic=26903
dfighter  : (01 January 2013 - 05:56 PM) Arcemu wishes you all a happy new year!
Hasbro  : (12 September 2012 - 10:01 AM) Please excuse our outage from the web! Our web host had a major malfunction!
dfighter  : (01 September 2012 - 04:05 PM) Since the spam bots just don't want to stop, I've enabled admin verification when registering.
dfighter  : (23 January 2012 - 09:56 PM) Please note that from now on you will need to confirm your email on the wiki in order to edit it!
Hasbro  : (31 December 2011 - 12:50 PM) Happy New Years all!
Navid  : (26 December 2011 - 04:09 AM) Merry Christmas !!!!!! Happy holidays all :)
WAmadeus  : (24 December 2011 - 03:54 PM) Merry Christmas to all!
dfighter  : (24 December 2011 - 11:05 AM) The Arcemu team wishes y'all a Merry Christmukkah!
Hasbro  : (05 October 2011 - 12:53 PM) Looking for web designers for upcoming web related project. If you're interested in designing user interfaces contact me
dfighter  : (02 September 2011 - 03:47 PM) So who here wants vehicles in Arcemu? :P http://arcemu.org/fo...showtopic=25440
Hasbro  : (14 August 2011 - 03:25 PM) Join us on irc, grab an irc client and connect to irc.freenode.net join channel #arcemu /server irc.freenode.net:6667 /join #arcemu
jackpoz  : (03 August 2011 - 05:33 AM) to all Lua Engine (old one) users: please check http://arcemu.org/fo...showtopic=25274
Hasbro  : (20 May 2011 - 05:27 PM) Looking for people experienced with CMake configuration and setup! Contact me asap
Hasbro  : (15 May 2011 - 05:03 PM) ArcEmu is recruiting C++ programmers, contact Hasbro if interested.
paroxysm  : (03 May 2011 - 06:26 PM) Updated luabridge gossip example to describe the whole gossip creation process rather than just how to create menu. Gossip tutorial
paroxysm  : (23 April 2011 - 11:35 AM) Lua writers can refer to the Luabridge Tutorials section in the Wiki to learn how to write gossip code correctly.
Hasbro  : (20 April 2011 - 05:22 PM) Thank you for your continuous contribution of bug reports, we are working on them.
Hasbro  : (17 April 2011 - 03:20 AM) Please consider donating to support our bills. Donations can be sent using PayPal to donations@arcemu.org - Thank you for your support.
paroxysm  : (10 April 2011 - 12:43 AM) Refer to the Luabridge Tutorials section in the Wiki to learn the new syntax of luabridge.
Resize Shouts Area

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Basic Npc Script

#1 User is offline   Earthful 

  • Newbie
  • Group: Members
  • Posts: 3
  • Joined: 27-August 09

Posted 26 February 2013 - 02:56 AM

So... I just went around looking at several forums and then pulled this little script together, made entirely by myself with credits to others for their tutorials (too many to list) but I'd like to thank ArcEMU Wikipedia the most.

I'm not sure how well this script works though... but I'm just trying to get the concept right and get it tested if possible, and once the script is working then I can polish it further. Let me know how I did with my first NPC script, and any feedbacks is wonderful!

Phase One (100-90%):
-Casts a simple harmless firebolt every two seconds.

Phase Two (90-50%):
-Casts http://www.wowhead.com/spell=121245 curse every 3 seconds.
-Casts http://www.wowhead.com/spell=69404 curse every 8 seconds.

Phase Three (50-20%):
-At beginning of the phase, http://www.wowhead.com/spell=36276 is applied, it is recommended to decurse it off the tank quickly then slowly take it off everyone.
-Casts http://www.wowhead.com/spell=121245 curse every 1.5 second.
-Strikes the tank with a powerful strike - http://www.wowhead.com/spell=83070 every 8.5 seconds.

Phase Four (20-0%):
-At beginning of the phase, all players have the following three curses casted on them;
http://www.wowhead.com/spell=36914
http://www.wowhead.com/spell=31651
http://www.wowhead.com/spell=36917
-Strikes the tank with a powerful strike - http://www.wowhead.com/spell=83070 every 7.5 seconds.
-Casts http://www.wowhead.com/spell=93278 every 1 second.


-- Basic NPC Script (UNTESTED)
-- Credits to Earthful
local NPC_ID = 0
local phaseStarted = {false,false,false,false}
function OnCombat(unit,event,target)
local pName = target:GetName()
local npcAtPullSay = "You're a fool to cross me, " .. pName .. ". Prepare to die!"
SendChatMessage(12, 0, npcAtPullSay)
unit:RegisterEvent(beginFight,1000,0)
end
function OnWipe()
SendChatMessage(12, 0, "Where did you go?")
unit:RemoveEvents()
end
function OnTargetDied()
SendChatMessage(12, 0, "All I wanted to do is to play with you...")
SendChatMessage(16, 0, "seems disappointed.")
end
function OnDied()
SendChatMessage(12, 0, "But... but... I'm not supposed to die?")
SendChatMessage(16, 0, "coughs violently and then dies.")
end
function beginFight(unit)
        local HP = unit:GetHealthPct()
        if( HP >= 90 && phaseStarted[1] == false ) then
         phaseStarted[1] == true
         Unit:RegisterEvent("phaseOne", 1000, 0)
        elseif( HP < 90 && HP >= 50 && phaseStarted[2] == false )
         Unit:RemoveEvents()
         SendChatMessage(12, 0, "Ah, so you want a challenge? You shall get one!")
         phaseStarted[2] == true
         Unit:RegisterEvent("phaseTwo", 1000, 0)
         unit:RegisterEvent(beginFight,1000,0)
        elseif( HP < 50 && HP >= 20 && phaseStarted[3] == false )
            Unit:RemoveEvents()
         SendChatMessage(14, 0, "NO! I am not weak and you will not get me easily!")
   for i,pPlayer in pairs(pUnit:GetInRangePlayers()) do
    unit:FullCastSpellOnTarget(36276,pPlayer) -- 36917
   end
         phaseStarted[3] == true
         Unit:RegisterEvent("phaseThree", 1000, 0)
         unit:RegisterEvent(beginFight,1000,0)
        elseif( HP < 20 && phaseStarted[4] == false )
            Unit:RemoveEvents()
            SendChatMessage(14, 0, "All of my fury shall be unleashed upon all those that oppose me.")
   for i,pPlayer in pairs(pUnit:GetInRangePlayers()) do
    unit:FullCastSpellOnTarget(36914,pPlayer)
    unit:FullCastSpellOnTarget(31651,pPlayer)
    unit:FullCastSpellOnTarget(36917,pPlayer)
   end
         phaseStarted[4] == true
         Unit:RegisterEvent("phaseFour", 1000, 0)
        end
end
function phaseOne(unit)
unit:RegisterEvent("fireBolt", 2000, 0)
end
function phaseTwo(unit)
unit:RegisterEvent("curseOne", 3000, 0)
unit:RegisterEvent("curseTwo", 8000, 0)
end
function phaseThree(unit)
unit:RegisterEvent("curseOne", 1500, 0)
unit:RegisterEvent("hitTank", 8500, 0)
end
function phaseFour(unit)
unit:RegisterEvent("lightningBlast", 1000, 0)
unit:RegisterEvent("hitTank", 7500, 0)
end
function fireBolt(unit)
unit:FullCastSpellOnTarget(43584,unit:GetRandomPlayer(0))
end
function curseOne(unit)
unit:FullCastSpellOnTarget(121245,unit:GetRandomPlayer(7))
end
function curseTwo(unit)
unit:FullCastSpellOnTarget(69404,unit:GetRandomPlayer(7))
end
function hitTank(unit)
unit:FullCastSpellOnTarget(83070,pUnit:GetMainTank())
end
function lightningBlast(unit)
unit:FullCastSpellOnTarget(93278,unit:GetRandomPlayer(7))
end
RegisterUnitEvent(NPC_ID,1,OnCombat)
RegisterUnitEvent(NPC_ID,2,OnWipe)
RegisterUnitEvent(NPC_ID,3,OnTargetDied)
RegisterUnitEvent(NPC_ID,4,OnDied)

0

#2 User is offline   Satanail 

  • Enthusiast
  • PipPipPip
  • Group: Members
  • Posts: 150
  • Joined: 11-March 12
  • Gender:Male
  • Location:Absurdistan
  • Server OS:Windows

Posted 26 February 2013 - 04:48 AM

You use some spells that are not excising in 3.3.5 so there is no way your npc will be able to cast them. Anyway the script itself should work fine, but if you plan to script too many things in lua, you should try to use as less functions as possible in order to minimize the RAM used by the server and etc. You might also have some problems with the phases if the npc is instanced. In this case the local "phaseStarted" will be messed up if the npc is in combat in more than one instance id.
0

#3 User is offline   Earthful 

  • Newbie
  • Group: Members
  • Posts: 3
  • Joined: 27-August 09

Posted 26 February 2013 - 10:25 AM

View PostSatanail, on 26 February 2013 - 04:48 AM, said:

You use some spells that are not excising in 3.3.5 so there is no way your npc will be able to cast them. Anyway the script itself should work fine, but if you plan to script too many things in lua, you should try to use as less functions as possible in order to minimize the RAM used by the server and etc. You might also have some problems with the phases if the npc is instanced. In this case the local "phaseStarted" will be messed up if the npc is in combat in more than one instance id.


Hi Satanail,

Thank you for your response. The spells are just a fill-in-blanks to see if I had the concept right, and I'm not too worried about instancing the NPC (for now, lets just say he is outside).

But I have to ask this, declaring functions without registering the functions itself takes up RAM? Otherwise, I basically clear up the events before each phase to minimize the amount of spells being casted by the NPC (I'm not sure if this reduces the RAM usage).

My second question is that if you have a suggestion for this code, can you please tell me how to "reduce" the amount of functions while retaining the functionality? I personally are not too worried about hardware costs since I have 16GB RAM rack with two Xeon Quad Cores, and I'm more focused on functionality (OOP/flexibility with what I can do with the language itself to WoW)
0

#4 User is offline   Satanail 

  • Enthusiast
  • PipPipPip
  • Group: Members
  • Posts: 150
  • Joined: 11-March 12
  • Gender:Male
  • Location:Absurdistan
  • Server OS:Windows

Posted 26 February 2013 - 04:09 PM

View PostEarthful, on 26 February 2013 - 10:25 AM, said:

Hi Satanail,

Thank you for your response. The spells are just a fill-in-blanks to see if I had the concept right, and I'm not too worried about instancing the NPC (for now, lets just say he is outside).

But I have to ask this, declaring functions without registering the functions itself takes up RAM? Otherwise, I basically clear up the events before each phase to minimize the amount of spells being casted by the NPC (I'm not sure if this reduces the RAM usage).

My second question is that if you have a suggestion for this code, can you please tell me how to "reduce" the amount of functions while retaining the functionality? I personally are not too worried about hardware costs since I have 16GB RAM rack with two Xeon Quad Cores, and I'm more focused on functionality (OOP/flexibility with what I can do with the language itself to WoW)

Yes, if you go crazy with the functions and you do lots of scripts you will have problems eventually. I mentioned that just to warn you that the lua scripts (event if written in the most efficient way) really load the server in relation to the same script done in C++. So avoid scripting many things in lua. And yes, there is a way to reduce the number of functions and i already explained it in another topic a while ago. I have no time to rewrite your script now, but am posting another script i made back then. When the boss is in combat, he only runs one AIUpdate event and there are no other functions and timed events. It is a little more complex but it has its advantages and if you check at the scripts, that come in the core directory, you will notice that they are done in a similar way.
SPELL_SHADOWHEAL = 37456 -- cast self
SPELL_SHADOWBOLT = 58827 -- main tank
----------------
SPELL_FROSTARMOR = 18100 -- cast self
SPELL_ICETOMB = 29670 -- random player
----------------
SPELL_FIRESHIELD = 37318 -- cast self
SPELL_FIREBALL = 41484 -- random player
----------------
SPELL_LIGHTNINGSHIELD = 59845 -- cast self
SPELL_LIGHTNINGBOLT = 52921 -- random player
----------------
SPELL_ARCANEBOLT = 59520 -- random player (ranged)
SPELL_DEATH = 5 -- random player

local self = getfenv(1)

function OnCombat(Unit, event)
Unit:SendChatMessage(14, 0, "Ha puny humans, you dare challenge me!")
self[tostring(Unit)] = {
	--------------
	shadowheal = 5, -- phase 1 spells
	shadowbolt = 6, -- phase 1 and start spells
	--------------
	frostarmor = 1, -- * phase 2 spells
	icetomb = 6, -- phase 2 spells
	-------------- 
	fireshield = 1, -- * phase 3 spells
	fireball = 6, -- phase 3 spells
	--------------
	lightningshield = 15, -- phase 4 spells
	lightningbolt = 2, -- phase 4 spells
	--------------
	arcanebolt = 4, -- phase 5 spells
	--------------
	death = 5, -- phase 6 spells
	--------------
	phaseid = 0 -- phase controller
}
Unit:RegisterAIUpdateEvent(1000)
end

function AIupdate(Unit)
if(Unit:IsCasting() ) then return end
	if(Unit:GetNextTarget() == nil) then
		Unit:WipeThreatList()
		return
	end
local vars = self[tostring(Unit)]
if(Unit:GetHealthPct() > 90)then -- start phase
	vars.shadowbolt = vars.shadowbolt - 1
	if(vars.shadowbolt <= 0)then
		Unit:FullCastSpellOnTarget(SPELL_SHADOWBOLT, Unit:GetMainTank())
		vars.shadowbolt = 6
	end
elseif(Unit:GetHealthPct() > 80 and Unit:GetHealthPct() <= 90 and vars.phaseid == 0)then -- phase 1 transition
	Unit:SendChatMessage(14, 0, "I shall never fall!")
	vars.phaseid = 1
elseif(Unit:GetHealthPct() > 80 and Unit:GetHealthPct() <= 90 and vars.phaseid == 1)then -- phase 1
	vars.shadowbolt = vars.shadowbolt - 1
	vars.shadowheal = vars.shadowheal - 1
	if(vars.shadowbolt <= 0)then
		Unit:FullCastSpellOnTarget(SPELL_SHADOWBOLT, Unit:GetMainTank())
		vars.shadowbolt = 6
	elseif(vars.shadowheal <= 0)then
		Unit:CastSpell(SPELL_SHADOWHEAL)
		vars.shadowheal = 5
	end
elseif(Unit:GetHealthPct() > 60 and Unit:GetHealthPct() <= 80 and vars.phaseid == 1)then -- phase 2 transition
	Unit:SendChatMessage(14, 0, "So you think that was hard, Ha!")
	Unit:SetModel(6209)
	vars.phaseid = 2
elseif(Unit:GetHealthPct() > 60 and Unit:GetHealthPct() <= 80 and vars.phaseid == 2)then -- phase 2
	if(Unit:HasAura(SPELL_FROSTARMOR) == false)then
		Unit:CastSpell(SPELL_FROSTARMOR)
	end
	vars.icetomb = vars.icetomb - 1
	if(vars.icetomb <= 0)then
		Unit:FullCastSpellOnTarget(SPELL_ICETOMB, Unit:GetRandomPlayer(0))
		vars.icetomb = 6
	end
elseif(Unit:GetHealthPct() > 40 and Unit:GetHealthPct() <= 60 and vars.phaseid == 2)then -- phase 3 transition
	Unit:SendChatMessage(14, 0, "Time for things to get hotter!")
	Unit:SetModel(1070)
	Unit:SetScale(2)
	if(Unit:HasAura(SPELL_FROSTARMOR))then
		Unit:RemoveAura(SPELL_FROSTARMOR)
	end
	vars.phaseid = 3
elseif(Unit:GetHealthPct() > 40 and Unit:GetHealthPct() <= 60 and vars.phaseid == 3)then -- phase 3
	if(Unit:HasAura(SPELL_FIRESHIELD) == false)then
		Unit:CastSpell(SPELL_FIRESHIELD)
	end
	vars.fireball = vars.fireball - 1
	if(vars.fireball <= 0)then
		Unit:FullCastSpellOnTarget(SPELL_FIREBALL, Unit:GetRandomPlayer(0))
		vars.fireball = 6
	end	
elseif(Unit:GetHealthPct() > 20 and Unit:GetHealthPct() <= 40 and vars.phaseid == 3)then -- phase 4 transition
	Unit:SetScale(1)
	if(Unit:HasAura(SPELL_FIRESHIELD))then
		Unit:RemoveAura(SPELL_FIRESHIELD)
	end
	Unit:SetModel(14515)
	vars.phaseid = 4
elseif(Unit:GetHealthPct() > 20 and Unit:GetHealthPct() <= 40 and vars.phaseid == 4)then -- phase 4
	vars.lightningshield = vars.lightningshield - 1
	vars.lightningbolt = vars.lightningbolt - 1
	if(vars.lightningshield <= 0)then
		Unit:CastSpell(SPELL_LIGHTNINGSHIELD)
		vars.lightningshield = 15
	elseif(vars.lightningbolt <= 0)then
		Unit:FullCastSpellOnTarget(SPELL_LIGHTNINGBOLT, Unit:GetRandomPlayer(0))
		vars.lightningbolt = 2
	end
elseif(Unit:GetHealthPct() > 5 and Unit:GetHealthPct() <= 20 and vars.phaseid == 4)then -- phase 5 transition
	if(Unit:HasAura(SPELL_LIGHTNINGSHIELD))then
		Unit:RemoveAura(SPELL_LIGHTNINGSHIELD)
	end
	Unit:SetModel(14253)
	vars.phaseid = 5
elseif(Unit:GetHealthPct() > 5 and Unit:GetHealthPct() <= 20 and vars.phaseid == 5)then -- phase 5
	vars.arcanebolt = vars.arcanebolt - 1
	if(vars.arcanebolt <= 0)then
		Unit:FullCastSpellOnTarget(SPELL_ARCANEBOLT, Unit:GetRandomPlayer(1))
	end
elseif(Unit:GetHealthPct() <= 5 and vars.phaseid == 5)then -- phase 6 transition
	Unit:SendChatMessage(14, 0, "Enough! This must end!")
	Unit:SetModel(3980)
	vars.phaseid = 6
elseif(Unit:GetHealthPct() <= 5 and vars.phaseid == 6)then -- phase 6
	vars.death = vars.death - 1
	if(vars.death <= 0)then
		Unit:FullCastSpellOnTarget(SPELL_DEATH, Unit:GetRandomPlayer(0))
	end
end
end

function OnDied(Unit, event)
Unit:SendChatMessage(14, 0, "How.. How can this be!")
Unit:RemoveEvents()
Unit:RemoveAIUpdateEvent()
Unit:DeMorph()
Unit:SetScale(1)
end

function OnLeaveCombat(Unit, event)
Unit:RemoveAura(SPELL_LIGHTNINGSHIELD)
Unit:RemoveAura(SPELL_FIRESHIELD)
Unit:RemoveAura(SPELL_FROSTARMOR)
Unit:SetScale(1)
Unit:RemoveEvents()
Unit:RemoveAIUpdateEvent()
Unit:DeMorph()
end

function OnKIllPlayer(Unit, event, pDied)
if(pDied:IsPlayer())then
	Unit:SendChatMessage(14, 0, "Ha your strength is puny!")
end
end

RegisterUnitEvent(38581,1,OnCombat)
RegisterUnitEvent(38581,2,OnLeaveCombat)
RegisterUnitEvent(38581,4,OnDied)
RegisterUnitEvent(38581,21,AIupdate)


The advantage here is that you can instance the creature or spawn many of them at the same time without any problems. You can also randomize the cast times of the spells by using math.random(lowest_delay,highest_delay) (i haven't done it in the script above but it is very easy to be done.)
0

#5 User is offline   Earthful 

  • Newbie
  • Group: Members
  • Posts: 3
  • Joined: 27-August 09

Posted 26 February 2013 - 10:56 PM

View PostSatanail, on 26 February 2013 - 04:09 PM, said:

Yes, if you go crazy with the functions and you do lots of scripts you will have problems eventually. I mentioned that just to warn you that the lua scripts (event if written in the most efficient way) really load the server in relation to the same script done in C++. So avoid scripting many things in lua. And yes, there is a way to reduce the number of functions and i already explained it in another topic a while ago. I have no time to rewrite your script now, but am posting another script i made back then. When the boss is in combat, he only runs one AIUpdate event and there are no other functions and timed events. It is a little more complex but it has its advantages and if you check at the scripts, that come in the core directory, you will notice that they are done in a similar way.

CODE BLOCK
...
END CODE

The advantage here is that you can instance the creature or spawn many of them at the same time without any problems. You can also randomize the cast times of the spells by using math.random(lowest_delay,highest_delay) (i haven't done it in the script above but it is very easy to be done.)


Yeah... this code is relatively simpler with only 5 functions verus 14 in my code :blink: thanks for the feedback!
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users