Fit my needs and maybe some of you too.
Also I want to know if there are any ways(there ever are) to improve this
Also I want to know if there are any ways(there ever are) to improve this
JASS:
library ReputationSystem requires Table, UnitIndexer //by edo494
/*
Table by Bribe - http://www.hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/
UnitIndexer by Nestharus - http://www.hiveworkshop.com/forums/jass-resources-412/system-unit-indexer-172090/
This is wrote mainly for my own needs
This system allows you to create factions(reputations) for instance shops with requirements of some reputation,
gain reputation when we kill some monster and also gain some reputation when for isntance quests are done
You can also deincrease reputation to punish not good done job and other stuff.
Together with custom units and techtree, you can even have shops with items which require you to have some amount
of reputation in order to buy those items.
note: When I say in API reputation I most likely mean reputation as currency and reputation itself is
referred as faction.
*/
//------------------------------------------------------------------------
/*
API: First is struct API, if you are too lazy to use it, under it is a normal funcion API
struct reputation
Normal API:
(s - static)function(arguments) > return type(if any) description
(s).create(string) > Reputation Creates a new faction with name
(s).createEx(string, integer) > Reputation Creates a new faction with name at starting value of reputation
.remove() Destroys a given faction
(s).setRank(integer rank, string, integer tonextrank) Creates a new rank(currently globally), like hostile, friendly, revered ...
.increase(integer howmany, integer forplayer) Adds reputation in given faction for a player
.decrease(integer howmany, integer forplayer) Lowers reputation in given faction for a player
.getName() > string returns a name of a faction
.repS2I(string name) > integer turns a name of a faction into an integer(id of a faction), if invalid returns 0
This method can be used to get a non referenced reputation by knowing its name.
.getRep(integer ofplayer) > integer returns a current standing of a player to faction(not Rank but value)
.getTypeById(integer id) > string returns a name of a rank by id(this is not bound to faction)
.getRankTypeOfPlayer(integer ofplayer) > string returns name of a current rank in given faction of player
.getRankOfPlayer(integer ofplayer) > integer returns a current rank in given faction of player(the same as GetCurrentRepTypeOfPlayer but as integer)
Trigger API:
global private constant boolean wanttoregister = true if you want to use TriggerRegisterRepChange, let it true, otherwise set to false
to shorten the code a little bit
.registerRepChangeEvent(code c, integer rankchange, boolean upside) registers a rankchange to trigger, the boolean tells
if it is upside or downside, whenever the reputation rank is changed
all functions registered to that reputation are executed regardless of how much
times the same function is there
Single Player API:
Those commands shouldnt be used in multiplayer games because they are not changed for each player differently
and doing so could desync the game.
.addToFaction(unit toadd) > boolean Bounds a unit to that faction. One unit can be in any number of factions
but that may cause problems in changing aggresivity.
If successful returns true, if already saved or invalid unit(null) returns false.
.removeFromFaction(unit toremove) > boolean Removes a unit from a faction. If successful returns true, otherwise returns false.
.defineHostility(integer rank) Defines at which rank the units start to be friendly/hostile in that faction. Default is: friendly at all time.
.changeFaction(boolean good) Immedietally forces the system to swtich all units in given faction to
friendly(true) or hostile(false)
(s).getOriginalOwner(unit u) > player returns a original owner of a unit bound to faction
(s).getOriginalOwnerId(unit u) > integer returns Id of original owner of a unit bound to faction
In case you dont like to use structs or methods, there is library under this one with a function API for this system.
*/
//------------------------------------------------------------------------
/*
Change note:
Version Log:
121107 - fixed a bug with CreateNewRepEx(prior to 121107 createEx) not
setting name of the reputation
- removed local variable j from remove method
- renamed all methods(check API to see new names)
- moved function API into separated library
- reworked how repS2I works (O(n) -> O(1) )
121104 - remoworked how .ChangeFaction() works in AddRep and LowerRep methods
- added 2 new methods: GetOriginalOwner and GetOriginalOwnerId as well as 2 functions
with the same name
121103 - Intial release
*/
//------------------------------------------------------------------------
globals
private constant boolean wanttoregister = true //If you plan on using RegisterRepChangeEvent let this true, otherwise set to false
endglobals
struct Reputation
private string reptypename
private static Table repname
private static integer maxreptype = 0
private static TableArray tab
private static TableArray tac
private static integer maxstack = 1
private static integer array pointtoname //sololy for .getName() so we can point to every instance, otherwise
//method repS2I would be O(n)
private static integer array repreq
private static integer array reqxp
/*
why all arrays instead of normal variables as reptypename may you ask?
I like array syntax more then struct syntax, also I dont need to declare another
integer(thistype) in every function Im passing integers not reputation or without allocation
and still can access the desired index. Example is in setRank
If I didnt have arrays I would have to declare another integer = waste of memory
*/
static method create takes string name returns thistype
local integer i = 0
local thistype this = .allocate()
set repname[StringHash(name)] = this
set pointtoname[this] = StringHash(name)
loop
set tac[i][this] = 0
exitwhen i == 15
set i = i + 1
endloop
set maxstack = this
return this
endmethod
static method createEx takes string name, integer startingrep returns thistype
local integer i = 0
local thistype this = .allocate()
set repname[StringHash(name)] = this
set pointtoname[this] = StringHash(name)
loop
set tac[i][this] = startingrep
exitwhen i == 15
set i = i + 1
endloop
return this
endmethod
method remove takes nothing returns nothing
local integer i = 0
set repname.string[this] = ""
set pointtoname[this] = 0
loop
set reqxp[tac[i][this]] = 0
set tab[i][this] = 0
exitwhen i == 15
set i = i + 1
endloop
set repreq[this] = 0
call .deallocate()
endmethod
static method setRank takes integer rank, string name, integer xpto returns nothing
//to make sure we can use struct syntax (something.something_else)
local thistype this = rank
//protection
if repreq[rank] == -1 then
return
endif
set repreq[rank] = -1
set this.reptypename = name
// to ensure that even when we get over the rep needed it will show the correct rep
set this = this + 1
set this.reptypename = name
set reqxp[rank] = xpto
set maxreptype = maxreptype + 1
endmethod
method changeFaction takes boolean good returns nothing
local unit u
local integer i = 1
loop
set u = GetUnitById(saver[this][i])
if good then
call SetUnitOwner(u, Player(15), true)
else
call SetUnitOwner(u, Player(12), true)
endif
exitwhen i == hunit[this]
set i = i + 1
endloop
endmethod
method increase takes integer howmany, integer forplayer returns nothing
local integer a = tab[forplayer][this]
local integer b = tac[forplayer][this]
set a = a + howmany
loop
exitwhen a < reqxp[b] or maxreptype == b
if a > reqxp[b] then
set a = a - reqxp[b]
set b = b + 1
endif
endloop
if b > hostile[this] and not changed[this] then
call .changeFaction(true)
set changed[this] = true
endif
static if wanttoregister then
if b > (tac[forplayer][this]) then
if regist[this].trigger[b*2-1] != null then
call TriggerEvaluate(regist[this].trigger[b*2-1])
endif
endif
endif
set tab[forplayer][this] = a
set tac[forplayer][this] = b
endmethod
method decrease takes integer howmany, integer forplayer returns nothing
local integer a = tab[forplayer][this]
local integer b = tac[forplayer][this]
set a = a - howmany
loop
exitwhen a > 0 or b == 0
if b <= 0 and a < 0 then
set a = 0
endif
set a = a + reqxp[b]
set b = b - 1
endloop
if b < hostile[this] and changed[this] then
call .changeFaction(false)
set changed[this] = false
endif
static if wanttoregister then
if b < (tac[forplayer][this]) then
if regist[this].trigger[b*2] != null then
call TriggerEvaluate(regist[this].trigger[b*2])
endif
endif
endif
set tab[this][forplayer] = a
set tac[forplayer][this] = b
endmethod
method getName takes nothing returns string
return repname.string[pointtoname[this]]
endmethod
static method repS2I takes string name returns integer
return repname[StringHash(name)]
endmethod
method getRep takes integer playerindex returns integer
return tab[playerindex][this]
endmethod
static method getTypeById takes integer id returns string
local thistype this = id
return this.reptypename
endmethod
method getRankTypeOfPlayer takes integer forplayer returns string
local thistype what = tac[forplayer][this]
return what.reptypename
endmethod
method getRankOfPlayer takes integer ofplayer returns integer
return tac[ofplayer][this]
endmethod
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
private static method onInit takes nothing returns nothing
set tab = TableArray[16]
set tac = TableArray[16]
set saver = TableArray[0x2000]
set repname = Table.create()
static if wanttoregister then
set regist = TableArray[0x2000]
endif
endmethod
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//Single Player commands:
private static TableArray saver
private static integer array hostile
private static integer array hunit
private static player array origown
private static boolean array changed
private static method update takes nothing returns nothing
local thistype i = 1
local integer forplayer = 0
local integer q
loop
set forplayer = 0
set q = tac[forplayer][i]
loop
if hostile[i] > q and not changed[i] then
call i.changeFaction(true)
elseif hostile[i] < q and changed[i] then
call i.changeFaction(false)
endif
exitwhen forplayer == 15
set forplayer = forplayer + 1
endloop
exitwhen i == maxstack
set i = i + 1
endloop
endmethod
method addToFaction takes unit u returns boolean
//double save protection
if saver[this][GetUnitUserData(u)] != GetUnitUserData(u) and u != null then
set saver[this][GetUnitUserData(u)] = GetUnitUserData(u)
set origown[GetUnitUserData(u)] = GetOwningPlayer(u)
set hunit[this] = hunit[this] + 1
call .update()
return true
else
return false
endif
endmethod
method removeFromFaction takes unit u returns boolean
//double free protection
if saver[this][GetUnitUserData(u)] == 0 or u == null then
return false
else
set saver[this][GetUnitUserData(u)] = 0
set hunit[this] = hunit[this] - 1
set origown[this] = null
return true
endif
endmethod
method defineHostility takes integer rank returns nothing
set hostile[this] = rank
call .update()
endmethod
// Register command:
static if wanttoregister then
private static TableArray regist
method registerRepChangeEvent takes code c, integer rankchange, boolean upside returns nothing
if upside then
if regist[this].trigger[rankchange*2-1] == null then
set regist[this].trigger[rankchange*2-1] = CreateTrigger()
endif
call TriggerAddCondition(regist[this].trigger[rankchange*2-1], Condition(c))
else
if regist[this].trigger[rankchange*2] == null then
set regist[this].trigger[rankchange*2] = CreateTrigger()
endif
call TriggerAddCondition(regist[this].trigger[rankchange*2], Condition(c))
endif
endmethod
endif
static method getOriginalOwner takes unit u returns player
return origown[GetUnitUserData(u)]
endmethod
static method getOriginalOwnerId takes unit u returns integer
return GetPlayerId(origown[GetUnitUserData(u)])
endmethod
endstruct
endlibrary
library ReputationSystemFunctionAPI requires ReputationSystem //by edo494
/*
Im not going to say what each function does, if you want to know, please reffer to their counterparts in struct
API:
function(arguments) -> return type(if any)...................................what the function does
CreateNewReputation(string name) -> reputation return Reputation.create(name)
CreateNewReputationEx(string name, integer startingrep) -> reputation return Reputation.createEx(name, startingrep)
RemoveReputation(Reputation rep) call rep.remove()
SetReputationRank(integer rank, string name, integer xpto) call Reputation.setRank(rank, name, xpto)
IncreaseReputation(Reputation rep, integer value, integer forplayer) call rep.increase(value, forplayer)
LowerReputation(Reputation rep, integer value, integer forplayer) call rep.decrease(value, forplayer)
GetReputationName(Reputation rep) -> string return rep.getName()
ReputationS2I(string s) -> integer return Reputation.repS2I(s)
GetCurrentReputation(Reputation rep, integer playerindex) -> integer return rep.getRep(playerindex)
GetRepTypeById(integer id) -> string return Reputation.getTypeById(id)
GetCurrentRepTypeOfPlayer(Reputation rep, integer playerindex) -> string return rep.getRankTypeOfPlayer(playerindex)
GetCurrentRankOfPlayer(Reputation rep, integer playerindex) -> integer return rep.getRankOfPlayer(playerindex)
//----------------------------------------------------------
Single Player API(Should not be used in multiplayer for 100% correct result)
ChangeFaction(Reputation rep, boolean flag) call rep.changeFaction(flag)
AddUnitToFaction(Reputation rep, unit u) call rep.addToFaction(u)
RemoveUnitFromFaction(Reputation rep, unit u) call rep.removeFromFaction(u)
DefineHostility(Reputation rep, integer rank) call rep.defineHostility(rank)
GetOriginalOwner(unit u) -> player return Reputation.getOriginalOwner(u)
function GetOriginalOwnerId(unit u) -> integer return Reputation.getOriginalOwnerId(u)
//----------------------------------------------------------
Trigger API, only works with global called wanttoregister == true
RegisterRepChangeEvent(reputation rep, code c, integer rank, boolean good) call rep.registerRepChangeEvent(c, rank, flag)
*/
// Function API:
function CreateNewReputation takes string name returns Reputation
return Reputation.create(name)
endfunction
function CreateNewReputationEx takes string name, integer startingrep returns Reputation
return Reputation.createEx(name, startingrep)
endfunction
function RemoveReputation takes Reputation rep returns nothing
call rep.remove()
endfunction
function SetReputationRank takes integer rank, string name, integer xpto returns nothing
call Reputation.setRank(rank, name, xpto)
endfunction
function IncreaseReputation takes Reputation rep, integer value, integer forplayer returns nothing
call rep.increase(value, forplayer)
endfunction
function LowerReputation takes Reputation rep, integer value, integer forplayer returns nothing
call rep.decrease(value, forplayer)
endfunction
function GetReputationName takes Reputation rep returns string
return rep.getName()
endfunction
function ReputationS2I takes string s returns integer
return Reputation.repS2I(s)
endfunction
function GetCurrentReputation takes Reputation rep, integer playerindex returns integer
return rep.getRep(playerindex)
endfunction
function GetRepTypeById takes integer id returns string
return Reputation.getTypeById(id)
endfunction
function GetCurrentRepTypeOfPlayer takes Reputation rep, integer playerindex returns string
return rep.getRankTypeOfPlayer(playerindex)
endfunction
function GetCurrentRankOfPlayer takes Reputation rep, integer playerindex returns integer
return rep.getRankOfPlayer(playerindex)
endfunction
function ChangeFaction takes Reputation rep, boolean flag returns nothing
call rep.changeFaction(flag)
endfunction
function AddUnitToFaction takes Reputation rep, unit u returns nothing
call rep.addToFaction(u)
endfunction
function RemoveUnitFromFaction takes Reputation rep, unit u returns nothing
call rep.removeFromFaction(u)
endfunction
function DefineHostility takes Reputation rep, integer rank returns nothing
call rep.defineHostility(rank)
endfunction
static if wanttoregister then
function RegisterRepChangeEvent takes Reputation rep, code c, integer rank, boolean flag returns nothing
call rep.registerRepChangeEvent(c, rank, flag)
endfunction
endif
function GetOriginalOwner takes unit u returns player
return Reputation.getOriginalOwner(u)
endfunction
function GetOriginalOwnerId takes unit u returns integer
return Reputation.getOriginalOwnerId(u)
endfunction
endlibrary
Last edited: