Wie Talentbaum implementieren ?
-
Hallo liebes C++ Forum,
Also ich habe jetzt gesucht nach "Skilltree, Talentbaum, Skillbaum, Skill Baum, Fähigkeitsbaum" etc. und war auch schon auf dem gamedev.net unterwegs. Aber ich habe meine Frage noch nicht so richtig beantworten können. Und zwar:
Wie kann ich einen Talentbaum, ähnlich wie in Diablo2,WoW,Spellforce2, Torchlight etc. etc. etc. implementieren?
Ich programmiere in c++ und schreibe aus Spass, als Hobby mit einem Freund an einem 2D Rollenspiel. Aber ich weiss einfach nicht, wie ich Talente einbauen kann.
Meine Idee war, dass jeder Charakter pro Level 1 Talentpunkt bekommt, den er in einen von 3 Bäumen investieren kann: Stärke, Magie, Geschick. In diesen Bäumen selbst gibt es dann sowohl passive als auch aktive Fähigkeiten. (Sowas wie "Pro Stufe in diesem Talent erhöht sich die Ausdauer um 3%)
Bei sowas wäre meine Idee ja einfach, sobald der Punkt verteilt ist, bei dem Player die Ausdauer um 3% zu erhöhen, aber ich möchte auch eine respecc funktion. Also dass man seine Talente später wieder verlernen kann und neu wählen.
Meine Überlegungen dazu waren bisher:
-Errechnen wieviel %Bonus es bereits gibt und ihn wieder abziehen.
-In der PlayerKlasse einen "Talentfaktor" einfügen, der dann je nach talentpunkt erhöht wird und beim respecc auf 0 zurückgesetzt wird.
Aber das erscheint mir alles nich sehr perfomant bzw. "professionell"
Jetzt bin ich am überlegen ob man der Playerclass vielleicht einen vektor oder eine std::list, map oder sonstiges spendieren sollte wo die Talente festgehalten werden und dann bei respecc einfach mit .clear geleert werden.
Wobei ich mich da wieder Frage, wie ich dann die Talente aus diesen containern im Kampf einbaue?
Muss ich dann jedesmal bei der Attack() Funktion durch iteriren und schauen:
if( Talent.Stufe() > x ) { Schaden += y }
Also wie ihr vielleicht merkt, ich weiss nicht wie ich da rangehen soll. Ich wäre über denkanstösse oder pseudocode sehr erfreut!
-
Fkscorpion schrieb:
-In der PlayerKlasse einen "Talentfaktor" einfügen, der dann je nach talentpunkt erhöht wird und beim respecc auf 0 zurückgesetzt wird.
Das klingt mir jetzt am vernünftigsten!?
-
mach dir eine einfache enum liste von faehigkeiten und eine kleine klasse/struct wie z.b.
enum Skills { armor, magic, speed, ... }; struct SkillItem { std::string name; Skill skill; float Score; };
und dann kannst du die talente in eine std::list oder vector oder... ablegen wenn der spieler darauf den punkt legt. die skillitem kannst du beim start aus dateien laden (simple kleine textdateien wo jeweil der name + skillname steht).
wenn du die skillliste aenderst, kannst du alle player skills auf 0 setzen und gehst die liste einmal durch und summierst es wieder auf.beim rollenspiel scheint es dann eher so zu sein, dass du wuerfelst, statt solche if-abfragen zu machen. also eher
Health = max(Health-max(rand()%MaxShadern-Talent(armor),0));
noch irgendwas klar?
-
Du kannst z.B. eine Struktur anlegen, die für jede erdenkliche Art von Skills oder Charakterwerten ( Stärke, leben, geschick, etc. ) eine Variable enthält.
Diese Struktur instanziierst du bei deinem charakter 4 mal.
1. Boni durch Talente
2. Boni durch Ausrüstung
3. Basiswerte des Charakters, einschließlich Boni durch Levelups ( die sind ja dauerhaft und unumkehrbar )
4. Die Summe aus den ersten dreien.
Jedes mal wenn sich eine der ersten drei Instanzen ändert, musst die vierte neu berechnen.struct Stats { double EnhancedDamage_Percent; int BonusDamage_Absolute; int BonusLife_Absolute; double EnhancedLife_Percent; ... };
-
Ich würde es so machen:
Du hast deinen Charakter und für den gibt es einen berechenbaren "Grundzustand", d.h. - um mal von Charakterleveln auszugehen - du kannst ganz genau die Attribute deines Charakters auf Level 10 berechnen: Wie viel Intellekt, Agilität etc. er besitzt. Das ist wichtig für das Respeccen / Reskillen. Zudem ist es wichtig, dass du deine Charaktere ausreichend manipulieren kannst, also z.B.
setDamageFactor()
etc. Sowas sollte aber ohnehin vorhanden sein (stell dir vor, du hast einen Ausrüstungsgegenstand, der den Schaden einfach um 5% erhöht).Ich würde dann ein Talent einfach als (abstrakte) Klasse implementieren, die eine spezielle execute()-Methode besitzt. In der Methode kannst du dann spezifizieren, was genau geschehen soll.
Beispiel: Talent erhöht Lebensanzahl prozentual um 2% (pro Stufe). Dann würdest du in deiner Talent-
execute()
-Methodecharacter.setHealthPointFactor(character.getHealthPointFactor() + 0.02);
schreiben.Natürlich musst die dir auch noch Merken, welche Talente geskillt wurden, um z.B. von "Erhöhe HP um 2%" (Stufe 1) auf "Erhöhe HP um 4%" (Stufe 2) zu kommen.
Beim Respeccen gehst du einfach in den Grundzustand deines Charakters über d,h. du resettest ihn sozusagen. Alternativ kannst du auch für jedes Talent sowas wie
rollback()
mitgeben, was die Wirkung umkehrt. Allerdings ist fraglich, ob das immer möglich ist.Bei dem Ansatz ist es eben so, dass dein Charakter verändert wird, und beim alleinigen Betrachten (d.h. ohne Informationen über Talente) nicht klar ist, wie er geskillt ist. Da aber die Talente mitgespeichert werden, sollte das kein Problem sein. Sind ja auch nur Ansätze (z.B. speichert man nur geskillte Talente oder alle möglichen und vermerkt, ob sie geskillt wurden?).
Mit dem System lassen sich auch Synergien (Grüße D2) und auch zusätzliche Fähigkeiten durch Talente (Grüße WoW) implementieren.
-
Hey, vielen Dank für eure Antworten!
Ich muss zugeben auf die Idee mit einem Struct bin ich erst garnicht gekommen.
Ich hatte die Werte einfach als unsigned int erstellt... Aber so ist es natürlich viel genialer.Es sieht jetzt ungefähr so aus:
enum Trait { Strength, Agility, Endurance, Intelligence, Wisdom }; //blubb struct Stat { unsigned int normal_Value; //Standardmäßiger, vom Level abhängiger, Wert ohne Buffs etc. double equipModPercentage; // % Modifikator durch Ausrüstung. (z.B. +5% Gesundheit) unsigned int equipMod; // Wert Modifikator durch Ausrüstung (z.B. + 10 Stärke) double talentModPercentage; // % Modifikator durch Talente double debuffModPercentage; // % Modifikator durch Schwächungszauber unsigned int total_Value; // Zusammengerechneter Wert des stats };
und in der Hero.hpp class Hero { //blubb void SetTraitFactor(Trait trait, double Factor); private: Stat Strength {5,0,0,0,0,5}; Stat Agility {....}; etc.
Jetzt kann ich bei Talenten und Armor ganz einfach die Hero.SetTraitFactor()
Funktion benutzen und angeben, welchen Trait ich ändern möchte. Der Rest wird dann per switch() ermittelt und geupdatet
Vielen dank nochmal für eure Hilfe!
P.S.:
Die Fertigkeiten im Talentbaum werden jetzt einfach in eine std::list per push.back() befördert und beim respecc, "einfach" wieder entfernt