Jump to content

Help with Fallout 2 Character Generator

Kimmaz

Hello, I wanted to create a random character creation "thing" for Fallout 1 & 2. I got the idea from this https://bgautochar.com/ But I have a small problem, or I dont know how to export or make it outside the editor program. I am using PyCharm, and created a Project. It looks very similar to programs for making websites and stuff. I have a "work in progress" code, that seems to be on track. So far I am able to create a character and output the info to a text file while using PyCharm.

Update: I installed Visual Studio Code. And started with a html page and css style sheet. then wrote the script using javascript. It was mainly to learn a bit of code writing. and I also want to try a random character in fallout 2 next time.

Thanks for any advice.

Spoiler

W7smUDg.png

(The HTML file is blank or default. I just thought I perhaps needed one since the program made it easy to create one.) 

from random import seed
from random import randint

# Makes this a function that I can call hopefully
def generate_character():
    # seed random number generator
    seed_input = input("Enter the Seed number 5 digits: ") # User can enter in any positive number
    seed(seed_input)
    # Selects filename used to store all date
    output_file = "output.html"

    # Determines gender
    gender = randint(0, 1)
    # Convert gender to written form for the user to read
    if gender == 1:
        gender = "Male"
    else:
        gender = "Female"
    # Determines the age of the character
    ageNum = randint(16, 35)
    # Convert the age to written form for the user to read
    ageText = {
        16: "Sixteen", 17: "Seventeen", 18: "Eighteen", 19: "Nineteen", 20: "Twenty",
        21: "Twenty One", 22: "Twenty Two", 23: "Twenty Tree", 24: "Twenty Four", 25: "Twenty Five",
        26: "Twenty Six", 27: "Twenty Seven", 28: "Twenty Eight", 29: "Twenty Nine", 30: "Thirty",
        31: "Thirty One", 32: "Thirty Two", 33: "Thirty Three", 34: "Thirty Four", 35: "Thirty Five",
    }
    # --- Generate character skills ---
    # List to store the 3 skills selected.
    skills = []
    # generate weapon skill, usable skill and passive skill and adding to skill list.
    weapon_skill = randint(1, 6)
    skills.append(weapon_skill)
    usable_skill = randint(7, 14)
    skills.append(usable_skill)
    passive_skill = randint(15, 18)
    skills.append(passive_skill)
    # Convert the skills to written form for the user to read
    skill_text = {
        1: "Small Guns", 2: "Big Guns", 3: "Energy Weapons", 4: "Unarmed", 5: "Melee Weapons", 6: "Throwing",
        7: "First Aid", 8: "Doctor", 9: "Sneak", 10: "Lockpick", 11: "Steal", 12: "Traps", 13: "Science", 14: "Repair",
        15: "Speech", 16: "Barter", 17: "Gambling", 18: "Outdoorsman",
    }
    # Writes text to the output file
    export_file = open(output_file, "w")
    export_file.write("<h2>Character Generated by Seed number " + str(seed_input) + ": </h2>")
    export_file.write("<p>You are a " + (ageText[ageNum]) + " year old " + gender + ".</p><p> Skills: ")
    for output in range(len(skills)):
        export_file.writelines([str(skill_text[skills[output]]) + ", "])
    export_file.write("</p>")
    # --- Generate character Traits ---

    # list to store the 0, 1 or 2 traits
    traits = ["", ""]
    # Convert the Traits to written form for the user to read
    traits_text = {
        1: "Fast Metabolism", 2: "Bloody Mess", 3: "Bruiser", 4: "Jinxed",
        5: "Small Frame", 6: "Good Natured", 7: "One Hander", 8: "Chem Reliant",
        9: "Finesse", 10: "Chem Resistant", 11: "Kamikaze", 12: "Sex Appeal",
        13: "Heavy Handed", 14: "Skilled", 15: "Fast Shot", 16: "Gifted"
    }
    # Determine how many traits you will have
    traits_num = randint(0, 2)
    if traits_num == 2:
        # To prevent 2 identical values
        while traits[0] == traits[1]:
            traits.clear()
            for numberoftraits in range(traits_num):
                generate_trait = randint(1, 16)
                traits.append(generate_trait)
                traits.sort()
    else:
        traits.clear()
        for numberoftraits in range(traits_num):
            generate_trait = randint(1, 16)
            traits.append(generate_trait)
    if not traits:
        export_file = open(output_file, "a")
        export_file.write("<p>You did not get any traits.</p>")
    else:
        export_file = open(output_file, "a")
        export_file.write("<p>Traits: ")
        for output in range(len(traits)):
            export_file.writelines(str(traits_text[traits[output]]) + ", ")
        export_file.write("</p>")
    # --- Generate character Main stats ---

    # Stores the value of S.P.E.C.I.A.L
    stats = [1, 1, 1, 1, 1, 1, 1]
    stats_text = ("Strength: ", "Perception: ", "Endurance: ", "Charisma: ", "Intelligence: ", "Agility: ", "Luck: ")
    total_points = 40
    if traits.count(3):     # If Bruiser, add 2 Strength
        total_points = total_points + 2
        stats[0] = stats[0] + 2
    if traits.count(5):     # If Small Frame, add 1 Agility
        total_points = total_points + 1
        stats[5] = stats[5] + 1
    if traits.count(16):    # If Gifted, add 1 every stat
        total_points = total_points + 7
        for attribute in range(len(stats)):
            stats[attribute] = stats[attribute] + 1
    while sum(stats) < total_points:    # 1. Checks if all stat points is distributed
        variable = randint(0, 6)        # 2. Determine what S.P.E.C.I.A.L to increase
        if stats[variable] < 10:        # 3. If value is 10(MAX) don't add and repeat from step 1
            stats[variable] = stats[variable] + 1   # 4. Adds 1 to the selected stat in stats table and repeat from step 1.

    # Writes text to the output file
    export_file.write("<p>S.P.E.C.I.A.L Stats:</p> <p>")
    for output in range(len(stats)):
        export_file.writelines([str(stats_text[output])] + [str(stats[output]) + "!"])
        export_file.write("<br>")
    export_file.write("</p>")
    export_file = open(output_file, "r")
    # Prints all the data in the console
    print(export_file.read())
    export_file.close()

# Without this line, nothing happens
generate_character()

Here is the current output to output.html that I would like to generate and view in a browser window, using local files on the pc. The formating and layout might change

Character Generated by Seed number 66414:
You are a Twenty Six year old Male.

Skills: Energy Weapons, Repair, Speech,

You did not get any traits.

S.P.E.C.I.A.L Stats:

Strength: 4!
Perception: 10!
Endurance: 6!
Charisma: 7!
Intelligence: 3!
Agility: 4!
Luck: 6!

 

Link to comment
Share on other sites

Link to post
Share on other sites

pycharm is just running it through the python interpreter in a terminal. if you want a gui you'll have to program it. if you want it to be a website you need to either do it in javascript or use a framework like django.

Don't ask to ask, just ask... please 🤨

sudo chmod -R 000 /*

Link to comment
Share on other sites

Link to post
Share on other sites

On 7/15/2020 at 2:33 PM, Sauron said:

pycharm is just running it through the python interpreter in a terminal. if you want a gui you'll have to program it. if you want it to be a website you need to either do it in javascript or use a framework like django.

I realized that. I made it in javascript. thanks for the advice. here is a working version. (not 100% finished) https://fallout2rcg.000webhostapp.com/

Link to comment
Share on other sites

Link to post
Share on other sites

The program is working, but I am not that great at coding. do you think it could be improved?

// Collects and stores data from the HTML page's 4 inputs. startButton, versionInput, traitSelect and skillSelect
const startButton_div = document.getElementById("startButton");
const version_input = document.getElementById("versionInput");
const traits_select = document.getElementById("traitSelect");
const skills_select = document.getElementById("skillSelect");
var traitChoiceValue;
var skillsChoiceValue;

// Stores the Traits. Is used in assignTraits() and assignPoints()
var traitsStored = [0, 0];

function assignTraits() {
    // Translate Traits to a readable message from random generated numbers.
    const traitsText = {
        1: "Fast Metabolism", 2: "Bloody Mess", 3: "Bruiser", 4: "Jinxed",
        5: "Small Frame", 6: "Good Natured", 7: "One Hander", 8: "Chem Reliant",
        9: "Finesse", 10: "Chem Resistant", 11: "Kamikaze", 12: "Sex Appeal",
        13: "Heavy Handed", 14: "Skilled", 15: "Fast Shot", 16: "Gifted"
    }

    // Resets the Traits stored to a equal value so that the "while" loop runs every time the Generate button is clicked
    traitsStored[0] = 0;
    traitsStored[1] = 0;

    // Prevents the program to give you the same Trait twice.
    while (traitsStored[0] == traitsStored[1]) {
        // Randomly selects 2 Traits and stores them for later use.
        for (i = 0; i < 2; i++) {
            var traitSelected = Math.floor(Math.random() * 16) + 1;
            traitsStored[i] = traitSelected;
        }
    }

    // Finds if the user wanted Random, No, One or Two Traits.
    traitChoiceValue = traits_select.options[traits_select.selectedIndex].value;

    // If the user choose "Random" it desides how many traits you will get here.
    if (traitChoiceValue == "random") traitChoiceValue = Math.floor(Math.random() * 3);

    //Values from traits_select was Strings and gave errors. This makes then Numbers before the Switch.
    if (typeof traitChoiceValue == "string") traitChoiceValue=Number(traitChoiceValue);

    //Chooses a message to be displayed on the page depending on what the user selected.
    switch (traitChoiceValue) {
        case 0:
            document.getElementById("traitResult_p").innerHTML = "You have no Traits";
            break;
        case 1:
            document.getElementById("traitResult_p").innerHTML = "Trait: " + traitsText[traitsStored[0]] + ".";
            break;
        case 2:
            document.getElementById("traitResult_p").innerHTML = "Traits: " + traitsText[traitsStored[0]] + " and " + traitsText[traitsStored[1]] + "!";
            break;
        default:
            document.getElementById("traitResult_p").innerHTML = "There was an error in the script! Received " + traitChoiceValue + " from the drop-down box." ;
            break;
    }
}

function assignSkills() {
    // Translate Skills to a readable message from random generated numbers.
    const skillText = {
        1: "Small Guns", 2: "Big Guns", 3: "Energy Weapons", 4: "Unarmed", 5: "Melee Weapons", 6: "Throwing",
        7: "First Aid", 8: "Doctor", 9: "Sneak", 10: "Lockpick", 11: "Steal", 12: "Traps", 13: "Science", 14: "Repair",
        15: "Speech", 16: "Barter", 17: "Gambling", 18: "Outdoorsman",
    }
    // Used in Math.random when the user selects Weapons (1-6), Usable (7-14), Passive (15-18).
    const skillesRangeIndex = [[6, 1], [8, 7], [4, 15]]

    // Stores the 3 Skills that is randomly selected, and Orderly Selected.
    var skillsStored_random = [0, 0, 0];
    var skillsStored_randomOrder = [0, 0, 0];

    // Finds how the user wanted his Skills picked.
    skillsChoiceValue = skills_select.options[skills_select.selectedIndex].value;

    // Makes sure that you don't get the same skill twice. You want 3 different skills.
    function skillsStored_random_Repeated() {
        value=false;
        if (skillsStored_random[0] == skillsStored_random[1]) value=true;
        if (skillsStored_random[0] == skillsStored_random[2]) value=true;
        if (skillsStored_random[1] == skillsStored_random[2]) value=true;
        if (skillsChoiceValue == "random_speech" && skillsStored_random.includes(15) ) value=true;
        return value;
    }

    // Generates 2 sets of Skills, used depending on user choice.
    while (skillsStored_random_Repeated()) {
        for (i = 0; i < 3; i++) {
            var skillSelected = Math.floor(Math.random() * skillesRangeIndex[i][0]) + skillesRangeIndex[i][1];
            skillsStored_randomOrder[i] = skillSelected;
            var skillSelected = Math.floor(Math.random() * 18) + 1;
            skillsStored_random[i] = skillSelected;
        }
    }

    // Sorts the Array Alfabeticly, so they are displayed in the correct order.
    skillsStored_random.sort(function(a, b){return a - b});

    //Chooses a message to be displayed on the page depending on what the user selected.
    switch (skillsChoiceValue) {
        case "random":
            document.getElementById("skillResult_p").innerHTML = "Skills: " + skillText[skillsStored_random[0]] + ", " + skillText[skillsStored_random[1]] + ", " + skillText[skillsStored_random[2]] + ".";
            break;
        case "random_order":
            // Gives you a Weapon skill, a usable skill and a passive skill.
            document.getElementById("skillResult_p").innerHTML = "Skills: " + skillText[skillsStored_randomOrder[0]] + ", " + skillText[skillsStored_randomOrder[1]] + ", " + skillText[skillsStored_randomOrder[2]] + ".";
            break;
        case "random_speech":
            // Gives you 2 random skills along with Speach as Skills.
            document.getElementById("skillResult_p").innerHTML = "Skills: " + skillText[skillsStored_random[0]] + ", " + skillText[skillsStored_random[1]] + ", " + skillText[15] + ".";
            break;
        case "first_char":
            // Gives you Small guns, Lockpick and Speach as Skills.
            document.getElementById("skillResult_p").innerHTML = "Skills: " + skillText[1] + ", " + skillText[10] + ", " + skillText[15] + ".";
            break;
    }
}

function assignPoints() {
    //Stores the SPECIAL values. starts at 1 because its the minimun in the game.
    var stats = [1, 1, 1, 1, 1, 1, 1];

    //Contains the ID="" of the 7 <td></td> elements that is used to display the stats on the screen.
    const statsText = ["Strength", "Perception", "Endurance", "Charisma", "Intelligence", "Agility", "Luck"];

    //If you are a Bruiser, Small framed or Gifted. You start with more stat points. They are added here.
    if (traitChoiceValue>0) {
        for (i=0; i<traitChoiceValue; i++) {
            if (traitsStored[i] == 3) stats[0]+=2;
            if (traitsStored[i] == 5) stats[5]++;
            if (traitsStored[i] == 16) 
                for (j=0; j<7; j++) stats[j]++;
        }
    }

    //Distributes points Randomly untill all 40 points (33+7) have been given out. One point at the time.
    var statsTotal = 0;
    while (statsTotal < 33) {
        var statsDist = Math.floor(Math.random() * 7);
        if (stats[statsDist] < 10) { //Max 10 points in each stat.
        stats[statsDist]++;
        statsTotal++;
        }
    }

    //Updates the webpage by writing the SPECIAL stats to it. One number at the time.
    for (i = 0; i < 7; i++) {
        document.getElementById(statsText[i]).innerHTML = stats[i];
    }
}

//This is triggered when you click the Generate button image. It starts the 3 main functions.
function main() {
    startButton_div.addEventListener('click', function() {
        assignTraits();
        assignSkills();
        assignPoints();
    })
}

//This is needed to start the function above when the page is loaded.
main()

 

Link to comment
Share on other sites

Link to post
Share on other sites

@Kimmaz Afaik, the only way to "import" a character in fallout2 is by modifying a savegame. Your character stats are supposed to be stored in the SAVE.DAT file.

 

A possible way to reverse engineer what you need is to modify a savegame with a existing character editor like falche2, only changing a single stat at a time, and checking which byte(s) changed by comparing the before and after. That way you can one by one find the relevant locations in the save file.

Link to comment
Share on other sites

Link to post
Share on other sites

@Unimportant Good idea, but I have no idea how to write that. I am pretty happy with a web-page that you can look at while starting your game. I leaned a bit of python and javascript and re-learned a bit of html and css. My creation can be fund here if you missed the link: https://fallout2rcg.000webhostapp.com/

 

I guess you mention it because https://bgautochar.com/  has that. Baldurs gate character creation has stats rolling, meaning you would have a hard time just looking at the web-page and creating the character in-game without a bit of lucky. you roll 3 x 6 sided dice for each stat so you get 3-18 in Strength, Dex, and so on. and so the total amount of points are not always the same. In Fallout 2 the sum of the SPECIAL is always the same before traits.

 

Perhaps I can try and learn how to write the website so its easier to use on mobile phone as a extension of the project. And also make it look a bit nicer on computer too.

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×