Files
galaxy-game/internal/controller/ship_group_send.go
T
2026-02-05 15:49:51 +02:00

120 lines
3.1 KiB
Go

package controller
import (
e "github.com/iliadenisov/galaxy/internal/error"
"github.com/iliadenisov/galaxy/internal/model/game"
"github.com/iliadenisov/galaxy/internal/util"
)
func (c *Controller) SendGroup(raceName string, groupIndex, planetNumber, quantity uint) error {
ri, err := c.Cache.raceIndex(raceName)
if err != nil {
return err
}
return c.Cache.SendGroup(ri, groupIndex, planetNumber, quantity)
}
func (c *Cache) SendGroup(ri int, groupIndex, planetNumber, quantity uint) error {
c.validateRaceIndex(ri)
sgi, ok := c.raceShipGroupIndex(ri, groupIndex)
if !ok {
return e.NewEntityNotExistsError("group #%d", groupIndex)
}
st := c.ShipGroupShipClass(sgi)
if st.DriveBlockMass() == 0 {
return e.NewSendShipHasNoDrivesError()
}
sourcePlanet, ok := c.ShipGroup(sgi).AtPlanet()
if !ok {
return e.NewShipsBusyError()
}
if c.ShipGroup(sgi).Number < quantity {
return e.NewBeakGroupNumberNotEnoughError("%d<%d", c.ShipGroup(sgi).Number, quantity)
}
p1, ok := c.Planet(sourcePlanet)
if !ok {
return e.NewGameStateError("source planet #%d does not exists", sourcePlanet)
}
p2, ok := c.Planet(planetNumber)
if !ok {
return e.NewEntityNotExistsError("destination planet #%d", planetNumber)
}
rangeToDestination := util.ShortDistance(c.g.Map.Width, c.g.Map.Height, p1.X.F(), p1.Y.F(), p2.X.F(), p2.Y.F())
if rangeToDestination > c.g.Race[ri].FlightDistance() {
return e.NewSendUnreachableDestinationError("range=%.03f", rangeToDestination)
}
if quantity > 0 && quantity < c.ShipGroup(sgi).Number {
nsgi, err := c.breakGroupSafe(ri, groupIndex, quantity)
if err != nil {
return err
}
sgi = nsgi
}
if p1.Number == p2.Number {
c.UnsendShips(c.ShipGroup(sgi))
c.JoinEqualGroups(ri)
return nil
}
c.LaunchShips(c.ShipGroup(sgi), planetNumber)
return nil
}
func (c *Cache) LaunchShips(sg *game.ShipGroup, destination uint) *game.ShipGroup {
for i := range c.ShipGroupsIndex() {
if c.ShipGroup(i).OwnerID == sg.OwnerID && c.ShipGroup(i).Index == sg.Index {
state := c.ShipGroup(i).State()
var p *game.Planet
switch state {
case game.StateInOrbit:
p = c.MustPlanet(sg.Destination)
case game.StateLaunched:
p = c.MustPlanet(sg.StateInSpace.Origin)
default:
panic("state invalid")
}
c.g.ShipGroups[i] = LaunchShips(*sg, destination, p.X.F(), p.Y.F())
return &c.g.ShipGroups[i]
}
}
panic("ship group not found")
}
func (c *Cache) UnsendShips(sg *game.ShipGroup) *game.ShipGroup {
for i := range c.ShipGroupsIndex() {
if c.ShipGroup(i).OwnerID == sg.OwnerID && c.ShipGroup(i).Index == sg.Index {
state := c.ShipGroup(i).State()
if state != game.StateLaunched {
panic("state invalid")
}
c.g.ShipGroups[i] = UnsendShips(*sg)
return &c.g.ShipGroups[i]
}
}
panic("ship group not found")
}
func LaunchShips(sg game.ShipGroup, destination uint, originX, originY float64) game.ShipGroup {
sg.StateInSpace = &game.InSpace{
Origin: sg.Destination,
X: game.F(originX),
Y: game.F(originY),
}
sg.Destination = destination
return sg
}
func UnsendShips(sg game.ShipGroup) game.ShipGroup {
sg.Destination = sg.StateInSpace.Origin
sg.StateInSpace = nil
return sg
}