package model import ( "sort" "strings" "github.com/iancoleman/strcase" "github.com/robertjanetzko/LegendsBrowser2/backend/util" "golang.org/x/exp/maps" "golang.org/x/exp/slices" ) func (w *DfWorld) process() { for id, r := range w.Rivers { r.Id_ = id } w.addRelationshipEvents() // set site in structure for _, site := range w.Sites { for _, structure := range site.Structures { structure.SiteId = site.Id_ } } w.processEvents() w.processCollections() w.processHistoricalFigures() for _, e := range w.Entities { if len(e.Sites) > 0 { if site, ok := w.Sites[e.Sites[0]]; ok { if site.Type_ == SiteType_Tower { e.Necromancer = true } } } for _, l := range e.EntityLink { if l.Type_ == EntityEntityLinkType_PARENT { e.Parent = l.Target } } idx := slices.Index(e.Child, e.Id_) if idx != -1 { e.Child = append(e.Child[:idx], e.Child[idx+1:]...) } sort.Slice(e.Wars, func(i, j int) bool { return e.Wars[i].Id_ < e.Wars[j].Id_ }) } if !w.Plus { trimRace := func(s string) string { return strings.Trim(strcase.ToDelimited(s, ' '), " 0123456789") } for _, hf := range w.HistoricalFigures { hf.Race = trimRace(hf.Race) } for _, e := range w.Entities { if len(e.Leaders) > 0 { switch r := e.Leaders[0].Hf.Race; { case r == "demon": e.Race = "goblin" default: e.Race = r } } else { if !strings.Contains(e.Name_, " ") { e.Race = "kobold" } } } for _, a := range w.DanceForms { a.Name_ = a.Description[:strings.Index(a.Description, " is a ")] } for _, a := range w.MusicalForms { a.Name_ = a.Description[:strings.Index(a.Description, " is a ")] } for _, a := range w.PoeticForms { a.Name_ = a.Description[:strings.Index(a.Description, " is a ")] } setEntityType := func(id int, t EntityType) { if c, ok := w.Entities[id]; ok { if c.Type_ == EntityType_Unknown { c.Type_ = t } } } setParent := func(id, parent int) { if id == -1 || parent == -1 { return } if c, ok := w.Entities[parent]; ok { if c.Parent != -1 { parent = c.Parent } } if c, ok := w.Entities[id]; ok { c.Parent = parent if p, ok := w.Entities[parent]; ok { c.Race = p.Race } } if c, ok := w.Entities[parent]; ok { c.Child = append(c.Child, id) } } list := maps.Values(w.HistoricalEvents) sort.Slice(list, func(i, j int) bool { return list[i].Id_ < list[j].Id_ }) for _, e := range list { switch d := e.Details.(type) { case *HistoricalEventCreatedSite: setParent(d.SiteCivId, d.CivId) setEntityType(d.CivId, EntityType_Civilization) setEntityType(d.SiteCivId, EntityType_Sitegovernment) case *HistoricalEventDestroyedSite: setParent(d.SiteCivId, d.DefenderCivId) setEntityType(d.AttackerCivId, EntityType_Civilization) setEntityType(d.DefenderCivId, EntityType_Civilization) setEntityType(d.SiteCivId, EntityType_Sitegovernment) case *HistoricalEventSiteTakenOver: setParent(d.SiteCivId, d.DefenderCivId) setParent(d.NewSiteCivId, d.AttackerCivId) setEntityType(d.DefenderCivId, EntityType_Civilization) setEntityType(d.SiteCivId, EntityType_Sitegovernment) setEntityType(d.AttackerCivId, EntityType_Civilization) setEntityType(d.NewSiteCivId, EntityType_Sitegovernment) case *HistoricalEventHfDestroyedSite: setParent(d.SiteCivId, d.DefenderCivId) setEntityType(d.DefenderCivId, EntityType_Civilization) setEntityType(d.SiteCivId, EntityType_Sitegovernment) case *HistoricalEventReclaimSite: setParent(d.SiteCivId, d.CivId) setEntityType(d.CivId, EntityType_Civilization) setEntityType(d.SiteCivId, EntityType_Sitegovernment) case *HistoricalEventCreatedStructure: setParent(d.SiteCivId, d.CivId) setEntityType(d.CivId, EntityType_Civilization) setEntityType(d.SiteCivId, EntityType_Sitegovernment) if site, ok := w.Sites[d.SiteId]; ok { if structure, ok := site.Structures[d.StructureId]; ok { if structure.Type_ == StructureType_Guildhall { setEntityType(d.SiteCivId, EntityType_Guild) } } } case *HistoricalEventChangedCreatureType: d.NewRace = trimRace(d.NewRace) d.OldRace = trimRace(d.OldRace) case *HistoricalEventCreatureDevoured: if col, ok := w.HistoricalEventCollections[e.Collection]; ok { if cd, ok := col.Details.(*HistoricalEventCollectionBeastAttack); ok { if len(cd.AttackerHfIds) > 0 { d.Eater = cd.AttackerHfIds[0] } } } d.Race = "creature" case *HistoricalEventHfNewPet: d.Pets = "creature" // TODO from hf pets? case *HistoricalEventItemStolen: if col, ok := w.HistoricalEventCollections[e.Collection]; ok { if cd, ok := col.Details.(*HistoricalEventCollectionBeastAttack); ok { if len(cd.AttackerHfIds) > 0 { d.Histfig = cd.AttackerHfIds[0] } d.Site = cd.SiteId } } d.ItemType = "item" case *HistoricalEventMasterpieceItem: d.ItemType = "item" } } for _, e := range w.Entities { switch e.Race { case "dwarf": e.EntityPosition = dwarfPositions case "elf": e.EntityPosition = elfPositions case "human": e.EntityPosition = humanPositions case "goblin": e.EntityPosition = goblinPositions } for i, p := range e.EntityPosition { p.Id_ = i } } } // check events texts for _, e := range w.HistoricalEvents { e.Details.Html(&Context{World: w}) } for _, e := range w.HistoricalEventCollections { e.Details.Html(e, &Context{World: w}) } } func (w *DfWorld) processEvents() { list := maps.Values(w.HistoricalEvents) sort.Slice(list, func(i, j int) bool { return list[i].Id_ < list[j].Id_ }) for _, e := range list { switch d := e.Details.(type) { case *HistoricalEventHfDoesInteraction: if hf, ok := w.HistoricalFigures[d.TargetHfid]; ok { if strings.HasPrefix(d.Interaction, "DEITY_CURSE_WEREBEAST_") { hf.Werebeast = true hf.WerebeastSince = e.Year } if strings.HasPrefix(d.Interaction, "DEITY_CURSE_VAMPIRE_") { hf.Vampire = true hf.VampireSince = e.Year } } case *HistoricalEventHfLearnsSecret: if strings.HasPrefix(d.Interaction, "SECRET_") { if hf, ok := w.HistoricalFigures[d.StudentHfid]; ok { hf.Necromancer = true hf.NecromancerSince = e.Year } } case *HistoricalEventCreatedSite: w.addEntitySite(d.CivId, d.SiteId) w.addEntitySite(d.SiteCivId, d.SiteId) w.Sites[d.SiteId].Ruin = false w.Sites[d.SiteId].Owner = d.CivId case *HistoricalEventDestroyedSite: w.addEntitySite(d.DefenderCivId, d.SiteId) w.addEntitySite(d.SiteCivId, d.SiteId) w.Sites[d.SiteId].Ruin = true case *HistoricalEventSiteTakenOver: w.addEntitySite(d.AttackerCivId, d.SiteId) w.addEntitySite(d.SiteCivId, d.SiteId) w.addEntitySite(d.DefenderCivId, d.SiteId) w.addEntitySite(d.NewSiteCivId, d.SiteId) w.Sites[d.SiteId].Ruin = false w.Sites[d.SiteId].Owner = d.AttackerCivId case *HistoricalEventHfDestroyedSite: w.addEntitySite(d.SiteCivId, d.SiteId) w.addEntitySite(d.DefenderCivId, d.SiteId) w.Sites[d.SiteId].Ruin = true case *HistoricalEventReclaimSite: w.addEntitySite(d.SiteCivId, d.SiteId) w.addEntitySite(d.SiteCivId, d.SiteId) w.Sites[d.SiteId].Ruin = false w.Sites[d.SiteId].Owner = d.CivId case *HistoricalEventAddHfEntityLink: if d.Link == HistoricalEventAddHfEntityLinkLink_Position { if hf, ok := w.HistoricalFigures[d.Hfid]; ok { for _, l := range hf.EntityPositionLink { if l.EntityId == d.CivId && l.StartYear == e.Year { l.PositionProfileId = d.PositionId } } for _, l := range hf.EntityFormerPositionLink { if l.EntityId == d.CivId && l.StartYear == e.Year { l.PositionProfileId = d.PositionId } } } } case *HistoricalEventHfReachSummit: id, _, _ := util.FindInMap(w.MountainPeaks, func(m *MountainPeak) bool { return m.Coords == d.Coords }) d.MountainPeakId = id case *HistoricalEventCreatedWorldConstruction: if master, ok := w.WorldConstructions[d.MasterWcid]; ok { master.Parts = append(master.Parts, d.Wcid) } case *HistoricalEventBuildingProfileAcquired: if site, ok := w.Sites[d.SiteId]; ok { if property, ok := site.SiteProperties[d.BuildingProfileId]; ok { if structure, ok := site.Structures[property.StructureId]; ok { structure.Ruin = false } d.StructureId = property.StructureId } } case *HistoricalEventRazedStructure: if site, ok := w.Sites[d.SiteId]; ok { if structure, ok := site.Structures[d.StructureId]; ok { structure.Ruin = true } } case *HistoricalEventReplacedStructure: if site, ok := w.Sites[d.SiteId]; ok { if structure, ok := site.Structures[d.OldAbId]; ok { structure.Ruin = true } } case *HistoricalEventAssumeIdentity: if hf, ok := w.HistoricalFigures[d.TricksterHfid]; ok { if id, ok := w.Identities[d.IdentityId]; ok { id.HistfigId = hf.Id_ } } case *HistoricalEventHfDied: if hf, ok := w.HistoricalFigures[d.SlayerHfid]; ok { hf.Kills = append(hf.Kills, d.Hfid) } } } } func (w *DfWorld) processCollections() { list := maps.Values(w.HistoricalEventCollections) sort.Slice(list, func(i, j int) bool { return list[i].Id_ < list[j].Id_ }) for _, col := range list { for _, eventId := range col.Event { if e, ok := w.HistoricalEvents[eventId]; ok { e.Collection = col.Id_ } } switch cd := col.Details.(type) { case *HistoricalEventCollectionAbduction: targets := make(map[int]bool) for _, eventId := range col.Event { if e, ok := w.HistoricalEvents[eventId]; ok { switch d := e.Details.(type) { case *HistoricalEventHfAbducted: targets[d.TargetHfid] = true } } } delete(targets, -1) cd.TargetHfids = util.Keys(targets) case *HistoricalEventCollectionBeastAttack: attackers := make(map[int]bool) for _, eventId := range col.Event { if e, ok := w.HistoricalEvents[eventId]; ok { switch d := e.Details.(type) { case *HistoricalEventHfSimpleBattleEvent: attackers[d.Group1Hfid] = true case *HistoricalEventHfAttackedSite: attackers[d.AttackerHfid] = true case *HistoricalEventHfDestroyedSite: attackers[d.AttackerHfid] = true case *HistoricalEventAddHfEntityLink: attackers[d.Hfid] = true case *HistoricalEventCreatureDevoured: attackers[d.Eater] = true case *HistoricalEventItemStolen: attackers[d.Histfig] = true } } } delete(attackers, -1) cd.AttackerHfIds = util.Keys(attackers) case *HistoricalEventCollectionJourney: HistoricalEventCollectionJourneyLoop: for _, eventId := range col.Event { if e, ok := w.HistoricalEvents[eventId]; ok { switch d := e.Details.(type) { case *HistoricalEventHfTravel: cd.TravellerHfIds = d.GroupHfid break HistoricalEventCollectionJourneyLoop } } } case *HistoricalEventCollectionOccasion: for _, eventcolId := range col.Eventcol { if e, ok := w.HistoricalEventCollections[eventcolId]; ok { switch d := e.Details.(type) { case *HistoricalEventCollectionCeremony: d.OccasionEventcol = col.Id_ case *HistoricalEventCollectionCompetition: d.OccasionEventcol = col.Id_ case *HistoricalEventCollectionPerformance: d.OccasionEventcol = col.Id_ case *HistoricalEventCollectionProcession: d.OccasionEventcol = col.Id_ } } } case *HistoricalEventCollectionWar: if e, ok := w.Entities[cd.AggressorEntId]; ok { e.Wars = append(e.Wars, col) } if e, ok := w.Entities[cd.DefenderEntId]; ok { e.Wars = append(e.Wars, col) } } } } func (w *DfWorld) addEntitySite(entityId, siteId int) { if e, ok := w.Entities[entityId]; ok { if !slices.Contains(e.Sites, siteId) { e.Sites = append(e.Sites, siteId) } } } func (w *DfWorld) addRelationshipEvents() { for _, r := range w.HistoricalEventRelationships { w.HistoricalEvents[r.Event] = &HistoricalEvent{ Id_: r.Event, Year: r.Year, Collection: -1, Seconds72: -1, Details: &HistoricalEventAddHfHfLink{ Hfid: r.SourceHf, HfidTarget: r.TargetHf, Relationship: r.Relationship, LinkType: HistoricalEventAddHfHfLinkLinkType_Unknown, }, } } } func (w *DfWorld) processHistoricalFigures() { // for _, hf := range w.HistoricalFigures { // for _, i := range hf.ActiveInteraction { // if strings.HasPrefix(i, "DEITY_CURSE_WEREBEAST_") { // hf.Werebeast = true // } // if strings.HasPrefix(i, "DEITY_CURSE_VAMPIRE_") { // hf.Vampire = true // } // if strings.HasPrefix(i, "SECRET_") { // hf.Necromancer = true // } // } // } }