ID:2017162
 
(See the best response by Ter13.)
Code:
mob
proc
Take_Damage(Amount,mob/Opponent,DType = "Physical",Direction = 0)
if(IsEnemy)
DieMob(Opponent)
DieMob(Opponent)
if(IsEnemy)
if(src.Health < 0)
Opponent:Train(round(src.Exp_Drop,1),Opponent:Train_Focus)


Problem description:Hi byond developers today im trying to make a party system with the options Create Party,invite.... but i want to add to it a exp distribution, what does it mean? it means that if a player from the party kills a mob send a part of the exp to the rest of members. Here i post a part of my take damage proc with the proc that executes the die of the enemy and exp gain if it helps.

Best response
Datums are perfect for this. A very basic party structure would look something like this.

Of course, it'd be up to you to design the rest.

mob
var/tmp
party/party
proc
GainExp(amt,source)
exp += amt
if(party&&source!=party)
party.GainedExp(src,amt)

party
var/tmp
list/members
proc
Join(mob/m)
if(!members)
members = list(m)
else
members += m
m.party = src

Leave(mob/m)
if(members)
members -= m
if(!members.len)
members = null
m.party = null

GainedExp(mob/m,amt)
for(var/mob/M in members-m)
m.GainExp(amt,src)

New(mem)
if(islist(mem))
for(var/mob/m in mem)
Join(m)
else if(mem)
Join(mem)
In response to Ter13
Okey let me see if i understand all the code:

Ter13 wrote:
Datums are perfect for this. A very basic party structure would look something like this.

Of course, it'd be up to you to design the rest.

> mob
> var/tmp // Temporal party
> party/party
> proc
> GainExp(amt,source) // Gain exp for the members in the party (Exp Distribution)
> exp += amt
> if(party&&source!=party) // If you are in party continue and get the exp, but what does mean source and what does?.
> party.GainedExp(src,amt) // Party gets the exp.
>
> party
> var/tmp
> list/members
> proc
> Join(mob/m) // Join to the party
> if(!members)
> members = list(m) // Players on the party
> else
> members += m
> m.party = src
>
> Leave(mob/m) // Leave the party
> if(members)
> members -= m
> if(!members.len)
> members = null
> m.party = null
>
> GainedExp(mob/m,amt)
> for(var/mob/M in members-m)
> m.GainExp(amt,src)
>
> New(mem)
> if(islist(mem))
> for(var/mob/m in mem)
> Join(m)
> else if(mem)
> Join(mem)
>


My question is: If i have defined gain exp on mob die and the killer is on the party he will get the exp 2 times?
If i have defined gain exp on mob die and the killer is on the party he will get the exp 2 times?

No. Pay close attention to party.GainedExp's list specifier in the loop. Notice I removed the player who gained the exp that triggered the function from the list?

No look at mob.GainExp(). Notice how I included the source argument, which will keep the players from retriggering the party.GainedExp() function?

It's properly gated.
To break it down further for you, say your mob kills a monster who gives out 16 XP, and you're in a party.

1) GainExp(16) is called for your mob; the source argument is null. You are given 16 XP.

2) Because you're in a party, and the XP you got did not come from that party (hence: if(party && source != party)), the proc will call party.GainedExp(src,16) to give out XP to everyone else. In the call it's telling the party how much XP to dole out and who already got it.

3) The party's GainedExp() goes through the list of all members except for you--you already got your XP--and calls player.GainExp(16,src), where here src is the party.

4) In friend.GainExp(16,party), each friend gets 16 XP, and then checks to see where the XP came from. Since the XP came from their party, there's nothing further that needs to be done.

The only thing here is, the code will give the exact same amount of XP out to all party members. If you want to split it up, you'll need to handle that another way. In that case I would do something like this:

mob/proc/GainExp(amt, source)
if(party && source != party)
party.GainedExp(amt)
else
exp += amt
LevelUp()

// You could use a weight of 1 to split XP evenly, or do some other formula.
// This one says a level 50 player gets 50x more XP than a level 1 partner.
#define PARTY_XP_WEIGHT(M) (M.level)

// Here we don't care who gave the XP, since it hasn't been given out already.
party/proc/GainedExp(amt)
var/weight, tot=0
var/mob/M
for(M in members)
tot += PARTY_XP_WEIGHT(M)
// Now that a total weight has been established, give out the XP; always round up.
for(M in members)
weight = M.level
M.GainExp(-round(-amt*PARTY_XP_WEIGHT(M)/tot), src)

Using the level as the weight I think works pretty nicely, since higher-level users usually contribute more to the killing but also need more XP, so this should cause the lower-level members to still get a nice gain without giving them tons and tons of XP all at once. But you could play with it; maybe sqrt(M.level) works better, or maybe something else.

Notice in that code, XP is not given out in advance; the party routine has to decide how much of the total to dole out to each member, and then calls GainExp() for each member. (This means that for the player who did the killing, it gets called twice: the first time merely hands off control to the party routine, and the second time is when they get the actual portioned-out XP.) I used -round(-value)) to round up since you probably want XP to be an integer, and rounding down is petty. This way every team member, no matter how inconsequential, gets at least 1 XP.
Hello everybody, I 'm trying to add a new tab party only with party members and I am thus putting the codes...What will I put wrong?! :/ But i'm with the idea of putting a tab with members of the party i joined, but already i broke my head and i could not

statpanel("Party")
        var/mob/m
        var/tmp/list/members
        for(m in members = list(m))
                members += m
                stat("Party Members - [m]")


but part of being a member of the party i already set this another method, and i put everything right but i have no idea what is going wrong and and missing expression error
In response to Yuriincrivel
mob/Stat()
if(party)
statpanel("Party")
stat(party.members)
..()