func (self *Region) PopulateEntities() { rng := terrain.GetCoordRNG(float64(self.X), float64(self.Y)) placeEntity := func(entType string) { // TODO: Find a way to figure this out. entW, entH := 1.0, 1.0 for { x := rng.Float64()*float64(self.Terrain.Width-2-uint(entW)) + 1 y := rng.Float64()*float64(self.Terrain.Height-2-uint(entH)) + 1 + entH if !self.Terrain.Hitmap.Fits(x, y, entW, entH) { continue } self.Spawn(entType, x, y) return } } switch self.Type { case terrain.REGIONTYPE_FIELD: entCount := rng.Intn(MAX_ENTITIES_PER_FIELD) for i := 0; i < entCount; i++ { var entType string if i%WOLF_ODDS == 0 { entType = "wolf" } else { entType = "sheep" } placeEntity(entType) } if self.IsTown() { soldierCount := rng.Intn(MAX_SOLDIERS_PER_TOWN-MIN_SOLDIERS_PER_TOWN) + MIN_SOLDIERS_PER_TOWN for i := 0; i < soldierCount; i++ { placeEntity("soldier") } placeEntity("bully") placeEntity("child") placeEntity("child") placeEntity("child") // placeEntity("trader") // self.Spawn("test", 50, 50) } case terrain.REGIONTYPE_SHOP: placeEntity("homely") placeEntity("homely") fallthrough case terrain.REGIONTYPE_HOUSE: placeEntity("homely") placeEntity("homely") if rng.Intn(SOLDIER_IN_HOUSE_ODDS) == 0 { placeEntity("soldier") } if rng.Intn(TRADER_IN_HOUSE_ODDS) == 0 { placeEntity("trader") } totalTiles := self.Terrain.Width * self.Terrain.Height for i := uint(0); i < totalTiles; i++ { tile := self.Terrain.Tiles[i%self.Terrain.Height][i/self.Terrain.Width] if tile == 58 { self.placeChestShop( float64(i/self.Terrain.Width), float64(i%self.Terrain.Height)+0.75, rng, ) } else if tile == 59 { self.placePotShop( float64(i/self.Terrain.Width), float64(i%self.Terrain.Height)+1, rng, ) } } case terrain.REGIONTYPE_DUNGEON: entCount := rng.Intn(MAX_ENTITIES_PER_DUNGEON) for i := 0; i < entCount; i++ { var entType string if i%DEATH_WAKER_ODDS == 0 { entType = "zombie" } else { entType = "death_waker" } placeEntity(entType) } } }
func (self *VirtualEntity) SetLocation(location EntityRegion) { self.location = location self.vm.Set("getX", func(call otto.FunctionCall) otto.Value { result, _ := self.vm.ToValue(self.x) return result }) self.vm.Set("getY", func(call otto.FunctionCall) otto.Value { result, _ := self.vm.ToValue(self.y) return result }) self.vm.Set("setCoords", func(call otto.FunctionCall) otto.Value { x, _ := call.Argument(0).ToFloat() y, _ := call.Argument(1).ToFloat() self.x, self.y = x, y return otto.Value{} }) self.vm.Set("setSize", func(call otto.FunctionCall) otto.Value { width, _ := call.Argument(0).ToFloat() height, _ := call.Argument(1).ToFloat() self.width, self.height = width, height return otto.Value{} }) self.vm.Set("sendEvent", func(call otto.FunctionCall) otto.Value { if self.location == nil { return otto.Value{} } self.location.Broadcast( self.location.GetEvent( events.GetType(call.Argument(0).String()), call.Argument(1).String(), self, ), ) return otto.Value{} }) self.vm.Set("getType", func(call otto.FunctionCall) otto.Value { eid, _ := call.Argument(0).ToString() entity := self.location.GetEntity(eid) if entity == nil { return otto.Value{} } result, _ := self.vm.ToValue(entity.Type()) return result }) self.vm.Set("getDistance", func(call otto.FunctionCall) otto.Value { entity := self.location.GetEntity(call.Argument(0).String()) if entity == nil { return otto.Value{} } x, y := self.BlockingPosition() dist := DistanceFrom(entity, x, y) result, _ := self.vm.ToValue(dist) return result }) self.vm.Set("getDistanceFrom", func(call otto.FunctionCall) otto.Value { entity := self.location.GetEntity(call.Argument(0).String()) x, _ := call.Argument(1).ToFloat() y, _ := call.Argument(2).ToFloat() dist := DistanceFrom(entity, x, y) result, _ := self.vm.ToValue(dist) return result }) self.vm.Set("getDistanceTo", func(call otto.FunctionCall) otto.Value { x, _ := call.Argument(0).ToFloat() y, _ := call.Argument(1).ToFloat() dist := DistanceFrom(self, x, y) result, _ := self.vm.ToValue(dist) return result }) self.vm.Set("getLevWidth", func(call otto.FunctionCall) otto.Value { result, _ := self.vm.ToValue(self.location.GetTerrain().Width) return result }) self.vm.Set("getLevHeight", func(call otto.FunctionCall) otto.Value { result, _ := self.vm.ToValue(self.location.GetTerrain().Height) return result }) self.vm.Set("attack", func(call otto.FunctionCall) otto.Value { x, _ := call.Argument(0).ToFloat() y, _ := call.Argument(1).ToFloat() weapon := call.Argument(2).String() self.location.Broadcast( self.location.GetEvent( events.DIRECT_ATTACK, fmt.Sprintf("%f %f %s", x, y, weapon), self, ), ) return otto.Value{} }) self.vm.Set("say", func(call otto.FunctionCall) otto.Value { message := call.Argument(0).String() x, y := self.BlockingPosition() nametag := self.Call("nametag") if nametag != "undefined" { nametag = nametag[1 : len(nametag)-1] message = fmt.Sprintf("<span class=\"nametag\">%s:</span> %s", nametag, message) } self.location.Broadcast( self.location.GetEvent( events.CHAT, fmt.Sprintf("%f %f\n%s", x, y, message), self, ), ) return otto.Value{} }) self.vm.Set("die", func(call otto.FunctionCall) otto.Value { log.Println("Entity death: ", self.id) self.location.Broadcast( self.location.GetEvent(events.DEATH, "", self), ) itemCodes := self.Call("getDrops") if itemCodes != "\"\"" && itemCodes != "undefined" { items := strings.Split(itemCodes, "\n") posX, posY := self.BlockingPosition() for _, item := range items { item = item[1 : len(item)-1] log.Println(self.id + " is dropping " + item) go func() { itemEnt := NewItemEntityInstance(item) itemEnt.location = self.location itemEnt.x = posX + (globalEntityRng.Float64()*3 - 1.5) itemEnt.y = posY + (globalEntityRng.Float64()*3 - 1.5) self.location.AddEntity(itemEnt) }() } } self.location.RemoveEntity(self) self.closing <- true return otto.Value{} }) self.vm.Set("spawn", func(call otto.FunctionCall) otto.Value { entType := call.Argument(0).String() radius, _ := call.Argument(1).ToFloat() entX, entY := self.BlockingPosition() rng := terrain.GetCoordRNG(entX, entY) terrain := self.location.GetTerrain() hitmap := terrain.Hitmap newEntW, newEntH := self.Size() for { newEntX := entX + (rng.Float64()-0.5)*radius*2 newEntY := entY + (rng.Float64()-0.5)*radius*2 if !hitmap.Fits(newEntX, newEntY, newEntW, newEntH) { continue } log.Println(self.id+" spawning "+entType, newEntX, newEntY) go self.location.Spawn(entType, newEntX, newEntY) break } return otto.Value{} }) self.Pass("setup", "null") self.gameTick() }