func manageNpc(npc types.NPC) { eventChannel := events.Register(npc) go func() { defer events.Unregister(npc) for { event := <-eventChannel switch e := event.(type) { case events.TickEvent: if npc.GetRoaming() { room := model.GetRoom(npc.GetRoomId()) exits := room.GetExits() exitToTake := utils.Random(0, len(exits)-1) model.MoveCharacter(npc, exits[exitToTake]) } case events.CombatStartEvent: if npc == e.Defender { combat.StartFight(npc, nil, e.Attacker) } case events.CombatStopEvent: if npc == e.Defender { combat.StopFight(npc) } case events.DeathEvent: if npc == e.Character { model.DeleteCharacter(npc.GetId()) return } } } }() }
func manageSpawner(spawner types.Spawner) { throttler := utils.NewThrottler(5 * time.Second) go func() { for { rooms := model.GetAreaRooms(spawner.GetAreaId()) if len(rooms) > 0 { npcs := model.GetSpawnerNpcs(spawner.GetId()) diff := spawner.GetCount() - len(npcs) for diff > 0 && len(rooms) > 0 { room := rooms[utils.Random(0, len(rooms)-1)] npc := model.CreateNpc(spawner.GetName(), room.GetId(), spawner.GetId()) npc.SetHealth(spawner.GetHealth()) manageNpc(npc) diff-- } } throttler.Sync() } }() }
func init() { fights = map[types.Character]combatInfo{} combatMessages = make(chan interface{}, 1) go func() { defer func() { recover() }() throttler := utils.NewThrottler(combatInterval) for { throttler.Sync() combatMessages <- combatTick(true) } }() go func() { for message := range combatMessages { Switch: switch m := message.(type) { case combatTick: for a, info := range fights { d := info.Defender if a.GetRoomId() == d.GetRoomId() { var power int skill := info.Skill if skill == nil { power = utils.Random(1, 10) } else { power = skill.GetPower() variance := utils.Random(-skill.GetVariance(), skill.GetVariance()) power += variance } d.Hit(power) events.Broadcast(events.CombatEvent{Attacker: a, Defender: d, Skill: skill, Power: power}) if d.GetHitPoints() <= 0 { Kill(d) } } else { doCombatStop(a) } } case combatStart: oldInfo, found := fights[m.Attacker] if m.Defender == oldInfo.Defender { break } if found { doCombatStop(m.Attacker) } fights[m.Attacker] = combatInfo{ Defender: m.Defender, Skill: m.Skill, } events.Broadcast(events.CombatStartEvent{Attacker: m.Attacker, Defender: m.Defender}) case combatStop: doCombatStop(m.Attacker) case combatQuery: _, found := fights[m.Character] if found { m.Ret <- true } else { for _, info := range fights { if info.Defender == m.Character { m.Ret <- true break Switch } } m.Ret <- false } default: panic("Unhandled combat message") } } }() }