Quest Engines
For easy quest making
For easy quest making
This is a package of two libraries; ItemQuestEngine and KillQuestEngine, both making it easier for the user to apply simple, boring-to-make quests. Everything is done with just a simple function call:
JASS:
call InitKillQuest(questunit,killunitrawcode,numberofkilledunits,rewardgold,rewardxp,questtitle,questicon,questdescription)
JASS:
call InitItemQuest(questunit,itemrawcode,numberofrecieveditems,rewardgold,rewardxp,questtitle,questicon,questdescription)
The two abilities needed uses 2 slightly edited models, each with 1 added attachment point, origin.
This makes attaching a neat ! for quests or ? for rewards above the units head much easier.
Now, I wanted this to be even more easy. So I decided to make those functions in the GUI too. If you want those two things to be available in GUI too, import the three .txt files I attached to this post into a folder named UI in the Warcraft III folder. If it's not there, create it. (This doesn't work if you have EGUI, WEU, UMSWE or any other GUI enhancing tool.)
Then copy the trigger category named Libraries from the attached map into the map you want to use the GUI functions in, and then you're done! Can't be much more easy, aye?
Now, I guess most of you would like to see the code right? Here it is;
JASS:
library KillQuestEngine
// configuration
globals
private constant integer INTEGER_PLAYERS=8 // number of players in the map
private constant integer RAWCODE_REWARD=039;A001039; // raw code of the 'Reward' ability
private constant integer RAWCODE_QUEST=039;A000039; // raw code of the 'Quest' ability
private constant string STRING_COLOR="|c00ff8000" // color of the messages
private constant real REAL_RANGE=160.000 // trigger range
private constant real REAL_DISPLAYTIME=6 // display time of the quest description
public boolean BOOL_REQ=false // quests is required? non-constant, you can always change
private constant boolean BOOL_EYECANDY=true // level-up eyecandy showed?
endglobals
// kill quests
private struct killquest
unit u
integer id
integer n
integer gold
integer xp
integer count
trigger t0
trigger t1
trigger t2
boolean b
// quest
string content
string name
string icon
quest q
method onDestroy takes nothing returns nothing
call DestroyTrigger(.t2)
endmethod
endstruct
globals
private killquest array KQ
private integer N=0
endglobals
private function True takes nothing returns boolean
return true
endfunction
private function onRange takes nothing returns boolean
local killquest kq
local integer j=N+1
local integer i=-1
local unit d=GetTriggerUnit()
if IsUnitType(d,UNIT_TYPE_HERO)==true then
loop
set j=j-1
exitwhen j<=0
set kq=KQ[j]
if kq.u==null then
return false
endif
//
loop
set i=i+1
exitwhen i>INTEGER_PLAYERS
call DisplayTextToPlayer(Player(i),0,0,"Quest Completed: "+STRING_COLOR+kq.name+".|r")
endloop
call SetPlayerState(GetOwningPlayer(d),PLAYER_STATE_RESOURCE_GOLD,GetPlayerState(GetOwningPlayer(d),PLAYER_STATE_RESOURCE_GOLD)+kq.gold)
call SetHeroXP(d,GetHeroXP(d)+kq.xp,BOOL_EYECANDY)
call QuestSetCompleted(kq.q,true)
call UnitRemoveAbility(kq.u,RAWCODE_REWARD)
call kq.destroy()
set N=N-1
endloop
endif
set d=null
return false
endfunction
private function onKill takes nothing returns boolean
local killquest kq
local integer j=N+1
local integer i=-1
local unit d=GetDyingUnit()
loop
set j=j-1
exitwhen j<=0
set kq=KQ[j]
if GetUnitTypeId(d)==kq.id then
set kq.count=kq.count+1
loop
set i=i+1
exitwhen i>INTEGER_PLAYERS
call DisplayTextToPlayer(Player(i),0,0,STRING_COLOR+GetUnitName(d)+"s|r killed: "+I2S(kq.count)+"/"+I2S(kq.n)+".")
endloop
if kq.count>=kq.n and kq.b==false then
call DestroyTrigger(kq.t1)
call TriggerRegisterUnitInRange(kq.t2,kq.u,REAL_RANGE,null)
call TriggerAddCondition(kq.t2,Condition(function onRange))
set kq.b=true
call UnitRemoveAbility(kq.u,RAWCODE_QUEST)
call UnitAddAbility(kq.u,RAWCODE_REWARD)
endif
endif
endloop
set d=null
return false
endfunction
private function AddQuest takes nothing returns boolean
local killquest kq
local integer j=N+1
local integer i=-1
local integer index=0
local boolexpr bxpr=Filter(function True)
if IsUnitType(GetTriggerUnit(),UNIT_TYPE_HERO)==true then
loop
set j=j-1
exitwhen j<=0
set kq=KQ[j]
loop
set i=i+1
exitwhen i>INTEGER_PLAYERS
call DisplayTimedTextToPlayer(Player(i),0,0,REAL_DISPLAYTIME,kq.content)
endloop
set kq.q=CreateQuest()
call QuestSetCompleted(kq.q,false)
call QuestSetIconPath(kq.q,kq.icon)
call QuestSetDescription(kq.q,kq.content)
call QuestSetRequired(kq.q,BOOL_REQ)
call QuestSetTitle(kq.q,kq.name)
call DestroyTrigger(kq.t0)
loop
call TriggerRegisterPlayerUnitEvent(kq.t1,Player(index),EVENT_PLAYER_UNIT_DEATH,bxpr)
set index=index+1
exitwhen index==bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddCondition(kq.t1,Condition(function onKill))
endloop
endif
set bxpr=null
return false
endfunction
function InitKillQuest takes unit u, integer id, integer n, integer gold, integer xp, string name, string icon, string content returns nothing
local killquest kq=killquest.create()
set kq.u=u
set kq.id=id
set kq.n=n
set kq.gold=gold
set kq.xp=xp
set kq.count=0
set kq.t0=CreateTrigger()
set kq.t1=CreateTrigger()
set kq.t2=CreateTrigger()
set kq.b=false
set kq.name=name
set kq.icon=icon
set kq.content=content
call UnitAddAbility(kq.u,RAWCODE_QUEST)
call TriggerRegisterUnitInRange(kq.t0,kq.u,REAL_RANGE,Filter(function AddQuest))
set N=N+1
set KQ[N]=kq
endfunction
endlibrary
JASS:
library ItemQuestEngine
globals
private constant integer INTEGER_PLAYERS=8 // number of players in the map
private constant integer INTEGER_MAXITEMS=100 // just the [] of the item array
private constant integer RAWCODE_REWARD=039;A001039; // raw code of the 'Reward' ability
private constant integer RAWCODE_QUEST=039;A000039; // raw code of the 'Quest' ability
private constant string STRING_COLOR="|c00ff8000" // color of the messages
private constant real REAL_RANGE=160.000 // trigger range
private constant real REAL_DISPLAYTIME=6 // display time of the quest description
public boolean BOOL_REQ=false // quests is required? non-constant, you can always change
private constant boolean BOOL_EYECANDY=true // level-up eyecandy showed?
endglobals
// item quests
private struct itemquest
unit u
integer id
integer n
integer gold
integer xp
integer count
trigger t0
trigger t1
trigger t2
boolean b
boolean req
item array ia[INTEGER_MAXITEMS]
// quest
string content
string name
string icon
quest q
method onDestroy takes nothing returns nothing
call DestroyTrigger(.t2)
endmethod
endstruct
globals
private itemquest array KQ
private integer N=0
endglobals
private function True takes nothing returns boolean
return true
endfunction
private function onRange takes nothing returns boolean
local itemquest kq
local integer j=N+1
local integer i=0
local unit d=GetTriggerUnit()
if IsUnitType(d,UNIT_TYPE_HERO)==true then
loop
set j=j-1
exitwhen j<=0
set kq=KQ[j]
if kq.u==null then
return false
endif
set KQ[j]=KQ[N]
set N=N-1
//
loop
set i=i+1
exitwhen i>kq.n
call RemoveItem(kq.ia<i>)
endloop
set i=-1
loop
set i=i+1
exitwhen i>INTEGER_PLAYERS
call DisplayTextToPlayer(Player(i),0,0,"Quest Completed: "+STRING_COLOR+kq.name+".|r")
endloop
call SetPlayerState(GetOwningPlayer(d),PLAYER_STATE_RESOURCE_GOLD,GetPlayerState(GetOwningPlayer(d),PLAYER_STATE_RESOURCE_GOLD)+kq.gold)
call SetHeroXP(d,GetHeroXP(d)+kq.xp,BOOL_EYECANDY)
call QuestSetCompleted(kq.q,true)
call UnitRemoveAbility(kq.u,RAWCODE_REWARD)
call kq.destroy()
endloop
endif
set d=null
return false
endfunction
private function onGetItem takes nothing returns boolean
local itemquest kq
local integer j=N+1
local integer i=-1
local item d=GetManipulatedItem()
loop
set j=j-1
exitwhen j<=0
set kq=KQ[j]
if GetItemTypeId(d)==kq.id then
set kq.count=kq.count+1
set kq.ia[kq.count]=d
loop
set i=i+1
exitwhen i>INTEGER_PLAYERS
call DisplayTextToPlayer(Player(i),0,0,STRING_COLOR+GetItemName(d)+"s|r recieved: "+I2S(kq.count)+"/"+I2S(kq.n)+".")
endloop
if kq.count>=kq.n and kq.b==false then
call DestroyTrigger(kq.t1)
call TriggerRegisterUnitInRange(kq.t2,kq.u,REAL_RANGE,null)
call TriggerAddCondition(kq.t2,Condition(function onRange))
set kq.b=true
call UnitRemoveAbility(kq.u,RAWCODE_QUEST)
call UnitAddAbility(kq.u,RAWCODE_REWARD)
endif
endif
endloop
set d=null
return false
endfunction
private function AddQuest takes nothing returns boolean
local itemquest kq
local integer j=N+1
local integer i=-1
local integer index=0
local boolexpr bxpr=Filter(function True)
if IsUnitType(GetTriggerUnit(),UNIT_TYPE_HERO)==true then
loop
set j=j-1
exitwhen j<=0
set kq=KQ[j]
loop
set i=i+1
exitwhen i>INTEGER_PLAYERS
call DisplayTimedTextToPlayer(Player(i),0,0,REAL_DISPLAYTIME,kq.content)
endloop
set kq.q=CreateQuest()
call QuestSetCompleted(kq.q,false)
call QuestSetIconPath(kq.q,kq.icon)
call QuestSetDescription(kq.q,kq.content)
call QuestSetRequired(kq.q,BOOL_REQ)
call QuestSetTitle(kq.q,kq.name)
call DestroyTrigger(kq.t0)
loop
call TriggerRegisterPlayerUnitEvent(kq.t1,Player(index),EVENT_PLAYER_UNIT_PICKUP_ITEM,bxpr)
set index=index+1
exitwhen index==bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddCondition(kq.t1,Condition(function onGetItem))
endloop
endif
set bxpr=null
return false
endfunction
function InitItemQuest takes unit u, integer id, integer n, integer gold, integer xp, string name, string icon, string content returns nothing
local itemquest kq=itemquest.create()
set kq.u=u
set kq.id=id
set kq.n=n
set kq.gold=gold
set kq.xp=xp
set kq.count=0
set kq.t0=CreateTrigger()
set kq.t1=CreateTrigger()
set kq.t2=CreateTrigger()
set kq.b=false
set kq.name=name
set kq.icon=icon
set kq.content=content
call UnitAddAbility(kq.u,RAWCODE_QUEST)
call TriggerRegisterUnitInRange(kq.t0,kq.u,REAL_RANGE,Filter(function AddQuest))
set N=N+1
set KQ[N]=kq
endfunction
endlibrary</i>
I tried to do as good as I could, and this was the outcome. (I looked it over many times, so I hope that there are no errors in my coding. ) It requires no other libraries, nothing. Just import into your map and edit the rawcodes to your needs.
Give credit to me when using.