Beispiel #1
0
func (d *Door) Interact(player world.PlayerLike, action string) {
	switch action {
	case "open":
		pos := d.Position()
		if pos == nil {
			return
		}
		x, y := pos.Position()
		px, py := player.Position().Position()
		if (px == x && py != y-1 && py != y+1) || (py == y && px != x-1 && px != x+1) || (px != x && py != y) {
			player.SetSchedule(&world.ScheduleSchedule{
				Schedules: []world.Schedule{
					world.NewWalkSchedule(x, y, true, uint(player.Weight()/player.WeightMax())),
					&world.ActionSchedule{
						Action:  "open",
						Target_: d.Outer().(world.Visible),
					},
				},
			})
			return
		}
		d.mtx.Lock()
		d.open = true
		d.mtx.Unlock()
		pos.Zone().Update(pos, d)
	case "close":
		pos := d.Position()
		if pos == nil {
			return
		}
		x, y := pos.Position()
		px, py := player.Position().Position()
		if (px == x && (py < y-1 || py > y+1)) || (py == y && (px < x-1 || px > x+1)) || (px != x && py != y) {
			player.SetSchedule(&world.ScheduleSchedule{
				Schedules: []world.Schedule{
					world.NewWalkSchedule(x, y, true, uint(player.Weight()/player.WeightMax())),
					&world.ActionSchedule{
						Action:  "close",
						Target_: d.Outer().(world.Visible),
					},
				},
			})
			return
		}
		d.mtx.Lock()
		d.open = false
		d.mtx.Unlock()
		pos.Zone().Update(pos, d)
	default:
		d.VisibleObject.Interact(player, action)
	}
}
Beispiel #2
0
func (f *Forge) Interact(player world.PlayerLike, action string) {
	switch action {
	default:
		f.VisibleObject.Interact(player, action)
	case "smelt":
		pos := f.Position()
		ppos := player.Position()
		if pos == nil || ppos == nil {
			return
		}
		x, y := pos.Position()
		if px, py := ppos.Position(); px != x || py != y+1 {
			player.SetSchedule(&world.ScheduleSchedule{
				Schedules: []world.Schedule{
					world.NewWalkSchedule(x, y, false, uint(player.Weight()/player.WeightMax())),
					&world.ActionSchedule{
						Target_: f,
						Action:  action,
					},
				},
			})
			return
		}
		ores := []interface{}{}
		for _, v := range player.Inventory() {
			if o, ok := v.(*Ore); ok {
				ores = append(ores, map[string]interface{}{
					"i": o.NetworkID(),
					"q": o.Material().Quality(),
					"v": o.Volume(),
					"w": o.Weight(),
				})
			}
		}
		for _, v := range player.Inventory() {
			if s, ok := v.(*Stone); ok {
				ores = append(ores, map[string]interface{}{
					"i": s.NetworkID(),
					"q": s.Material().Quality(),
					"v": s.Volume(),
					"w": s.Weight(),
				})
			}
		}
		instance := player.Instance(f.Position())
		var done time.Time
		instance.Last(func(last time.Time) time.Time {
			done = last
			return last
		})
		contents := []interface{}{}
		instance.Items(func(items []world.Visible) []world.Visible {
			for _, i := range items {
				var sprites []map[string]interface{}
				for j, c := range i.Colors() {
					sprites = append(sprites, map[string]interface{}{
						"S": i.Sprite(),
						"C": c,
						"E": map[string]interface{}{
							"y": j,
						},
					})
				}
				contents = append(contents, sprites)
				// 4 minutes per 5kg of ore
				done = done.Add(time.Minute * 4 * time.Duration(i.(world.Item).Weight()) / 5000)
			}
			if done.Before(time.Now()) && len(items) > 0 {
				materials := make(map[MetalType]*material)
				var quality big.Int
				var totalVolume uint64
				var tmp big.Int
				for _, i := range items {
					if o, ok := i.(*Ore); ok {
						for _, m := range o.material.components {
							if m.metal == nil || m.volume == 0 {
								continue
							}
							mat := materials[*m.metal]
							if mat == nil {
								mat = &material{metal: m.metal}
								materials[*m.metal] = mat
							}
							totalVolume += m.volume
							mat.volume += m.volume
							tmp.SetUint64(m.volume)
							quality.Add(&quality, tmp.Mul(&o.material.quality, &tmp))
						}
					}
				}
				originalVolume := totalVolume
				quality.Div(&quality, tmp.SetUint64(totalVolume))
				makeIngot := func(volume uint64) {
					ingot := &Ingot{}
					world.InitObject(ingot)
					ingot.material = &Material{
						components: make([]*material, 0, len((materials))),
						quality:    quality,
					}
					world.InitObject(ingot.material)
					remaining := originalVolume
					for _, m := range materials {
						v := m.volume * volume / remaining
						remaining -= m.volume
						volume -= v
						ingot.material.components = append(ingot.material.components, &material{
							metal:  m.metal,
							volume: v,
						})
					}
					ingot.material.sortComponents()
					if !player.GiveItem(ingot) {
						player.Position().Add(ingot)
					}
				}
				for totalVolume != 0 {
					if totalVolume <= 1000 {
						makeIngot(totalVolume)
						break
					}
					makeIngot(1000)
					totalVolume -= 1000
				}
				items = items[:0]
				contents = contents[:0]
			}
			return items
		})
		player.SetHUD("forge", map[string]interface{}{
			"O": ores,
			"C": contents,
			"T": done,
		})
	}
}