Example #1
0
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()
}