ID:1803805
 
(See the best response by Tarundbz.)
Code:
    Scale()
set src in view(4)
set category = null
if(!usr.isduel) return
if(Control!=usr) return

if(usr.PZ1!=src&&usr.PZ2!=src) return

scale_b = input("Scale?","[name]","[scale_b]") as num

if(scale_b<=0) scale_b = 1
if(scale_b>24) scale_b = 24
if(scale_r!=scale_b) scale_r = scale_b

for(var/client/M) if(M.mob) if(src in M.mob.SeeDuel) M << output({"<br><center><b>[usr.name]</b> has set the Scales of <i>[name]</i> to[scale_b]</b><br><b>Scale:</b><i>[scale_b]</i></center>"}, "chat_duel.output")


Problem description:

So I'm an iconer. Not really a coder. I do have programming experience in other languages but I'm still pretty fresh to the syntax on byond.

The game I helped out on recently had their owner/programmer decide he didn't have the time for the game anymore and passed everything to me. So I'm trying to get things going again and I'm running into an issue here.

This code above is to change a value assigned to a card in the game.

It's ment to ask for the Input from the player from a right-click command. ("Scale"). It takes the input, makes sure it's not less than 1 and not more than 24 then assigns it to 2 scales on the card.

This portion of the code works fine.

For some reason the chat output doesn't seem to work and I cannot for the life of me figure out why. I've been essentially teaching myself by working with the functioning coding.

The coding should result in...
If I were to change the scale of my card named XYZ to 20.

"IceFire2050 has set the Scales of XYZ to 20."

And it should only output that line to players viewing or participating in the game and it's outputted to our duel chat window.

Im basically building this using existing code as a template for now...

For example though...
for(var/mob/M in world) if(usr in M.SeeDuel) M << output({"<br><center><font color=#[font]><b>[name]</b> [emote]</font></center>"}, "chat_duel.output")

This output for a similar command works fine.

Can anyone help? I feel like I'm just overlooking this but I've been working on various things here for hours and I can't seem to pin it down.
Best response
for(var/mob/M in world) if(usr in M.SeeDuel)

you dont have to use all these
usr << output("<br><center><font color=#[font]><b>[name]</b> [emote]</font></center>","chat_duel.output")
In response to Tarundbz
Tarundbz wrote:
> for(var/mob/M in world) if(usr in M.SeeDuel)
>

you dont have to use all these
> usr << output({"<br><center><font color=#[font]><b>[name]</b> [emote]</font></center>"}, "chat_duel.output")
>


Wouldn't that output to everyone though? There could be multiple people playing in different matches at a time. This should only output this text to the players viewing this 1 particular instance.
In response to IceFire2050
not everyone but only to the the player it will be sent that message whose changing the value
It also needs to be sent to the player's opponent and any of the players observing their match.
for(var/mob/M) if(usr in M.SeeDuel) M << output("<br><center><b>[usr.name]</b> has set the Scales of <i>[name]</i> to[scale_b]</b><br><b>Scale:</b><i>[scale_b]</i></center>","chat_duel.output")

to the person who are playing the match with the fighter and also the obervers
In response to Tarundbz
Tarundbz wrote:
for(var/mob/M in world) if(usr in M.SeeDuel)


That will only output to the verb user. If they're dueling another player, then the inner "if" will match twice during the loop and they'll get double output, whereas their opponent won't get any.

I believe you meant this:

for(var/mob/M in world)
if(M in usr.SeeDuel)
M << output( ... )

Although even better would be:

for(var/client/C in world)
if(C.mob in usr.SeeDuel)
C.mob << output( ... )
In response to Tarundbz
Tarundbz wrote:
> for(var/mob/M in world) if(usr in M.SeeDuel)
>

you dont have to use all these
> usr << output("<br><center><font color=#[font]><b>[name]</b> [emote]</font></center>","chat_duel.output")
>


This is sincerely an awful approach to be recommending.

For starters, there's absolutely no reason to be looping through every mob in the world. Second, the if in statement doesn't even make sense. I'm assuming that M.SeeDuel is a list of players that can see the current duel.

You acknowledge that this shouldn't show the output to everyone later:

not everyone but only to the the player it will be sent that message whose changing the value

Why, if you only want to output to the person who can see the duel would you be looping through every player? It just doesn't make sense. You should be keeping track of observers and participants in duels, since you are going to be using that information later. If you want to use something later, it's much better to store it in memory than to do what you currently are.

This entire thing smacks of really backward design.

My advice? Abstract your dueling system behind a datum. It'll make it a lot easier to work with if you keep track of the information you are going to need later, rather than having to search through the world for every player that could potentially be involved with a duel every time you want to send a message.

#define PLAYER1 1
#define PLAYER2 2
#define OBSERVERS 4
#define EVERYONE 7

duel
var
mob/participant1
mob/participant2
list/observers
proc
ShowMessage(msg,flags=EVERYONE)
if(flags&PLAYER1)
participant1 << msg
if(flags&PLAYER2)
participant2 << msg
if(flags&OBSERVERS)
observers << msg

GetOpponent(mob/mob)
if(mob==participant1)
return participant2
else if(mob==participant2)
return participant1
else
return null

Left(mob/mob)
if(mob==participant1)
Win(participant2)
else if(mob==participant2)
Win(participant1)
else
observers -= mob
if(observers.len==0)
observers = null

Join(mob/m)
if(!observers)
observers = list()
observers |= m

Win(mob/winner)
//do whatever happens on win here
Cleanup()

Cleanup()
participant1.duel = null
participant2.duel = null
participant1 = null
participant2 = null
for(var/mob/m in observers)
m.duel = null
observers = null

mob
var
duel/duel
Logout()
if(duel)
duel.Left(src)
src.loc = null


The above is a basic implementation that will get around all of the problems you seem to be running into because of poor design on the dueling system. In my opinion, it's better to abstract all of the behavior of a duel into a single datum. This datum can be used to keep track of who your players in the duel are, as well as keep track of observers. This way, you don't have to search through the whole world every time you want to send a message to someone.

Tarun's example was... Well, I can't say it in a nicer way: Nonsense.
Just putting my two cents in here, if a list contains nothing but mob/client references, you can output directly to it without looping (ala 'world').

M.SeeDuel << output("Hello world!")


No reason to complicate the matter...