But if the host attacks two at once, only one will get knocked back and take damage, and the other one will become invincible.
This one is easy and isn't a multiplayer quirk! When the host overlaps two enemies, your Enemy_Hurt function is only running for one of the instances. This is because functions called on picked instances will only be called for ONE of the picked instances. If you want to have a function run for each picked instance you need to add a For Each before you run the function
The reason the not-damaged enemy becomes invincible is because every action BEFORE the function IS able to run on all picked instances, meaning the enemy's Hurt variable is being set to 1, but he's not running the Enemy_hurt function, and so his Hurt never returns to 0
The peer cannot do any damage, probably because he or the enemies are not synced right.
In your code you have it so when the Peer is overlapping an enemy AND the peer's input 4th bit is set to 1, the peer will damage the enemy. The problem is with the 4th bit never being set to 1 by non-host peers. Here's where the problem is in your code:
+ Touch: On tap gesture on Attack_Button
----+ System: getbit(Peer.inputs, 4) = 0
-----> Peer: Set Inputs to setbit(Self.inputs, 4, 1)
You're not specifying that the peer should be checking and setting the bits for THEIR peer. Since you don't specify, the code is probably picking the first instance, which is the host's peer object. This is why it works for the host, because they are accidentally picking their own peer
Also, most of your enemy code should be in the Host group. You don't want peers running logic for the enemies because things can happen differently on the Host's computer and the Peer's computer, resulting in mismatches game states and weird glitches. The peers should only be TOLD what is happening by the host (using the object syncing and via messages)
For the enemies, they will hop towards the crystal stand unless they get attacked. Then they are supposed to attack the last peer that hit them. For some reason they will not attack the peers; they will not move at all after being struck.
This is another problem that is not multiplayer-specific but is just how C3 works. Here's the code where the problem is:
+ Enemies: Hurt = 0
----+ Enemies: Last_Hit_PeerID = ""
-----> Enemies: Set 8Direction vector X to cos(angle(Self.X,Self.Y,Crystal.X,Crystal.Y)) × Self.8Direction.Maxspeed
-----> Enemies: Set 8Direction vector Y to sin(angle(Self.X,Self.Y,Crystal.X,Crystal.Y)) × Self.8Direction.Maxspeed
----+ System: Else
----+ Peer: PeerID = Enemies.Last_Hit_PeerID
-----> Enemies: Set 8Direction vector X to cos(angle(Self.X,Self.Y,Peer.X,Peer.Y)) × Self.8Direction.Maxspeed
-----> Enemies: Set 8Direction vector Y to sin(angle(Self.X,Self.Y,Peer.X,Peer.Y)) × Self.8Direction.Maxspeed
I'll translate what is happening
Pick ALL enemies where Hurt = 0
From those enemies, go through them all and check which ones have a Last_Hit_By_Peerid variable that is set to ""
For THOSE enemies, run movement logic
NOW we skip past the 'else' because the first condition was met. There were enemies that had a Last_Hit_By_Peerid variable that is set to "", so the condition was true and the 'else' is skipped. You probably expected your code to treat all the enemies with an empty variable one way and all the other enemies another way. What actually happened is if there are ANY enemies who match the first condition, the second is skipped entirely
To fix this you have some options
1. Remove the else (This will go through your group of Hurt = 0 Enemies twice. Once to check for enemies with an empty Last Hit By variable and another time to check for enemies WITH a valid Last Hit By Variable)
2. Add a For Each after Enemies: Hurt = 0 (This will run through each Enemy seperately, one at a time, and you can leave the else)
These options may have different impacts on performance, which you can test for yourself
Hope this helps :)