package data import ( json "github.com/json-iterator/go" "github.com/oylshe1314/framework/util" "sort" ) type Drop struct { Id int `json:"id"` DropId int `json:"drop_id"` BoxId int `json:"box_id"` BoxRate int `json:"box_rate"` MinNum int `json:"min_num"` MaxNum int `json:"max_num"` ItemId int `json:"item_id"` ItemNum int `json:"item_num"` ItemRate int `json:"item_rate"` } type dropItem struct { drop *Drop } type dropBox struct { boxId int rate int min int max int rates int items []*dropItem } type dropStore struct { dropId int boxes map[int]*dropBox } type DropTable struct { l []*Drop m map[int]*dropStore } func (this *DropTable) load(buf []byte) error { var err = json.Unmarshal(buf, &this.l) if err != nil { return err } this.m = make(map[int]*dropStore) for _, drop := range this.l { var item = &dropItem{drop} var store = this.m[item.drop.DropId] if store == nil { store = &dropStore{ dropId: drop.DropId, boxes: map[int]*dropBox{ item.drop.BoxId: { boxId: item.drop.BoxId, rate: item.drop.BoxRate, min: item.drop.MinNum, max: item.drop.MaxNum, rates: item.drop.ItemRate, items: []*dropItem{item}, }, }, } this.m[drop.DropId] = store } else { var box = store.boxes[item.drop.BoxId] if box == nil { box = &dropBox{ boxId: item.drop.BoxId, rate: item.drop.BoxRate, min: item.drop.MinNum, max: item.drop.MaxNum, rates: item.drop.ItemRate, items: []*dropItem{item}, } store.boxes[item.drop.BoxId] = box } else { box.rates += item.drop.ItemRate box.items = append(box.items, item) } } } for _, store := range this.m { for _, box := range store.boxes { sort.Slice(box.items, func(i, j int) bool { return box.items[i].drop.Id < box.items[j].drop.Id }) } } return nil } // Drop 掉落算法 func (this *DropTable) Drop(dropId int, times int) [][2]int { if dropId <= 0 { return nil } if times <= 0 { return nil } var store = this.m[dropId] if store == nil { return nil } var rd = util.NewRand() var result [][2]int for range times { for _, box := range store.boxes { if len(box.items) == 0 { continue } if rd.Float64()*10000.0 > float64(box.rate) { continue } var dropNum = box.min if box.max > dropNum { dropNum += rd.IntN(box.max - box.min) } var rates = float64(box.rates) var factor = rd.Float64() * rates for _, item := range box.items { rates -= float64(item.drop.ItemRate) if factor >= rates { result = append(result, [2]int{item.drop.ItemId, item.drop.ItemNum * dropNum}) break } } } } return result }