{$MODE OBJFPC} { -*- delphi -*- } {$INCLUDE settings.inc} unit researchbits; interface uses storable, rpc, actors, facilities; type TResearchFacility = class(TFacility) // @RegisterFacilityClass private FHandleDiscoveryProc: TDiscoveryNotificationProc; procedure RegisterSelfWithDynasty(); // XXX we don't yet support the parent's dynasty changing dynamically protected FLastResearchedTopic, FSelectedResearchTopic: UTF8String; FTimeStudied: TDateTime; FResearchPoints: TTechnologyPoints; function GetResearchTopics(): TResearchTopicList; procedure HandleSetResearchTopic(var Message: TMessage); message 'set-research-topic'; procedure HandleDiscovery(Actor: TAbstractActor; Kinds: TTechnologyTreeNodeKindSet); public procedure Init(Actor: TAbstractActor); override; destructor Destroy(); override; constructor Read(Stream: TReadStream); override; procedure Write(Stream: TWriteStream); override; procedure Tick(Interval: TDateTime); override; published property ResearchTopics: TResearchTopicList read GetResearchTopics; property SelectedResearchTopic: UTF8String read FSelectedResearchTopic; end; TPrayerFacility = class(TFacility) // @RegisterFacilityClass protected FPrayerCount: Cardinal; procedure HandlePray(var Message: TMessage); message 'pray'; public constructor Read(Stream: TReadStream); override; procedure Write(Stream: TWriteStream); override; published property Prayers: Cardinal read FPrayerCount; end; implementation uses stringstream; procedure TResearchFacility.Init(Actor: TAbstractActor); begin Assert(Assigned(Actor)); Assert(Actor is TOwnableActor); Assert(Assigned((Actor as TOwnableActor).CurrentOwnerDynasty)); inherited; Assert(Actor = Parent); FHandleDiscoveryProc := @HandleDiscovery; RegisterSelfWithDynasty(); FSelectedResearchTopic := (Parent as TOwnableActor).CurrentOwnerDynasty.GetDefaultResearchTopic(); FLastResearchedTopic := FSelectedResearchTopic; end; destructor TResearchFacility.Destroy(); begin Assert(Assigned(Parent)); Assert(Parent is TOwnableActor); Assert(Assigned((Parent as TOwnableActor).CurrentOwnerDynasty)); (Parent as TOwnableActor).CurrentOwnerDynasty.RemoveDiscoveryWatcher(@FHandleDiscoveryProc); inherited; end; constructor TResearchFacility.Read(Stream: TReadStream); begin inherited; FHandleDiscoveryProc := @HandleDiscovery; FLastResearchedTopic := Stream.ReadString(); FTimeStudied := Stream.ReadDouble(); FSelectedResearchTopic := Stream.ReadString(); FResearchPoints := TTechnologyPoints(Stream.ReadDouble()); Stream.AddFinalFixer(@RegisterSelfWithDynasty); end; procedure TResearchFacility.RegisterSelfWithDynasty(); begin Assert(Assigned(Parent)); Assert(Parent is TOwnableActor); Assert(Assigned((Parent as TOwnableActor).CurrentOwnerDynasty)); (Parent as TOwnableActor).CurrentOwnerDynasty.AddDiscoveryWatcher(@FHandleDiscoveryProc, [tkTopic]); end; procedure TResearchFacility.Write(Stream: TWriteStream); begin inherited; Stream.WriteString(FLastResearchedTopic); Stream.WriteDouble(FTimeStudied); Stream.WriteString(FSelectedResearchTopic); Stream.WriteDouble(TTechnologyPoints(FResearchPoints)); end; function TResearchFacility.GetResearchTopics(): TResearchTopicList; begin Assert(Assigned(Parent)); Assert(Parent is TOwnableActor); Assert(Assigned((Parent as TOwnableActor).CurrentOwnerDynasty)); Result := (Parent as TOwnableActor).CurrentOwnerDynasty.GetResearchTopics(); end; procedure TResearchFacility.HandleSetResearchTopic(var Message: TMessage); var Topic: UTF8String; Response: TStringStreamWriter; begin Assert(Assigned(Parent)); Assert(Parent is TOwnableActor); Assert(Assigned((Parent as TOwnableActor).CurrentOwnerDynasty)); Topic := Message.Stream.ReadString(); if (Message.Stream.ReadEnd()) then begin if ((Parent as TOwnableActor).CurrentOwnerDynasty <> Message.Dynasty) then begin Response := Message.Reply(False); end else if ((Parent as TOwnableActor).CurrentOwnerDynasty.VerifyResearchTopic(Topic)) then begin FSelectedResearchTopic := Topic; MarkDirty([dfNeedSave, dfNeedNotifications, dfNeedTick]); Response := Message.Reply(True); end else begin Response := Message.Reply(False); end; Response.Close(); end; end; procedure TResearchFacility.Tick(Interval: TDateTime); begin Assert(Assigned(Parent)); Assert(Parent is TOwnableActor); Assert(Assigned((Parent as TOwnableActor).CurrentOwnerDynasty)); // assumption: if FSelectedResearchTopic changed, it _just_ changed // the reality is that the ticker will be run at most one second after the topic changed // some lag here is realistic, anyway, so the second or so is ok // it's not user-visible, anyway FResearchPoints := FResearchPoints + Interval * kSecondsPerDay; if (FLastResearchedTopic <> '') then (Parent as TOwnableActor).CurrentOwnerDynasty.DoSomeResearch(Parent as TOwnableActor, Interval, FResearchPoints, FLastResearchedTopic, FTimeStudied); if (FLastResearchedTopic <> FSelectedResearchTopic) then begin FTimeStudied := 0.0; FLastResearchedTopic := FSelectedResearchTopic; end else begin FTimeStudied := FTimeStudied + Interval; end; MarkDirty([dfNeedSave]); end; procedure TResearchFacility.HandleDiscovery(Actor: TAbstractActor; Kinds: TTechnologyTreeNodeKindSet); begin if (tkTopic in Kinds) then MarkDirty([dfNeedNotifications]); end; constructor TPrayerFacility.Read(Stream: TReadStream); begin inherited; FPrayerCount := Stream.ReadCardinal(); end; procedure TPrayerFacility.Write(Stream: TWriteStream); begin inherited; Stream.WriteCardinal(FPrayerCount); end; procedure TPrayerFacility.HandlePray(var Message: TMessage); var Prayer: UTF8String; begin Prayer := Message.Stream.ReadString(); if (Message.Stream.ReadEnd()) then begin Writeln('RECEIVED PRAYER!!!! ', Prayer); Message.Reply(True).Close(); Inc(FPrayerCount); MarkDirty([dfNeedNotifications, dfNeedSave]); end; end; initialization {$INCLUDE registrations/researchbits.inc} end.