Author Topic: Falko's Mod Collection-generating rulesets with python  (Read 23054 times)

Offline Falko

  • Commander
  • *****
  • Posts: 802
    • View Profile
Falko's Mod Collection-generating rulesets with python
« on: April 27, 2014, 12:23:12 pm »
i played around with openxcom mods for some time now
and decided to publish what i created
perhaps somebody find the stuff useful

i put all the files in zip file

IMHO the most interesting part is a python script that allows to generate complex mods with 2-3 lines
Code: [Select]
research=[x["name"] for x in orig["research"] if x["cost"]>0]
changes=dict(research=[])
for r in research:
    changes["research"].append(dict(name=r,cost=2))
mods["Cheat_FastResearch"]=changes
that one is one of my testing/cheat mods and sets all (normal) research cost very low (you can get to cydonia in a month) - writing that manually is tedious work

unfortunately i did not document anything but the part outside the modcreation itself is 30 lines therefore i see no need :)
you need python of course and the pyaml library https://pyyaml.org/


now the the mods i generated
there is a list of cheating/testing mods that are useful to test something later game if you need to start  a new game for your mod (WARNING can suck all the fun out of the game!)
Cheat_Fundingx10: multiplies starting funds and available nation-funds times 10
Cheat_Supersoldiers: all soldiers have 200 in all stats
Cheat_Bob_the_Builder: all facilities are build within 2 days
Cheat_FastResearch: all research is done in 1-2 days with 1 scientist
Cheat_SuperFacilities: psi/work/labroom,defence,storage, quarter, crafts is multiplied with 10
Cheat_NoDamageAlien: aliens and alien weapons do no damage (chrysalid still makes zombies)


Medikit_need_alien_and_room: the medikit needs 2 normal aliens, 1 terrorist and one of (EXAMINATION_ROOM, ALIEN_SURGERY, ALIEN_REPRODUCTION [see https://www.openxcom.com/mod/alien-reproduction]) researched until this is accomplished i use https://openxcom.org/forum/index.php?topic=1782.msg19567#msg19567


Break2Elerium: my first mod was a converter of "plasma clips" into elerium because i thought the use of the "terran plasma weapons" https://openxcom.org/forum/index.php?topic=1710.0 and one of the "plasma beam needs elerium"-mods could lead into shortage but it was manageable without this mod but it is a nice example haow to "Manufacturing several items from one piece of material" or using different (optional) source material to get the same item
there are 4 version with different elerium output/costs i use the 50%-version

Craft Research Needs UFOs: Ufoconstruction and the following crafts need up to 6 researched Engineer/UFOs to appear in the research list

Failed .. Research 1 to ..: Puts "empty" Research object to the navigators,medics,... you have to collect more of them to get things done -Failed NAVIGATOR Research 1 to 1 means for each existing mission there is one failed Mission a navigator can give during interrogation.

since the rul files are produced via script be aware the layout/format is slightly different than the normaly used xcomrulset-format but still valid.

have fun :)

PS:
thanks to all the people in irc for the help
« Last Edit: May 12, 2014, 10:39:23 pm by Falko »

Offline civilian

  • Colonel
  • ****
  • Posts: 154
    • View Profile
Re: Falko's Mod Collection-generating rulesets with python
« Reply #1 on: April 27, 2014, 01:17:15 pm »
Interesting and clever mods. i like the elerium-recycler idea the most!  :)

Offline Falko

  • Commander
  • *****
  • Posts: 802
    • View Profile
Re: Falko's Mod Collection-generating rulesets with python
« Reply #2 on: April 28, 2014, 08:50:42 am »
Code: [Select]
changes=dict(units=[],items=[])
explodecorpselist={}
for u in orig["units"]:
    if u.get("race","") in alienraces or u.get("rank","")=="STR_LIVE_TERRORIST":       
        if u.get("specab",1)==1 :
            explodecorpselist[u["race"]]=explodecorpselist.get(u["race"],[])+[u["stats"]["strength"]]
            changes["units"].append(dict(type=u["type"],specab=1))
for i in orig["items"]:
    if i["type"].replace("_CORPSE","") in explodecorpselist:
        p=i.get("power",max(50,int(min(explodecorpselist[i["type"].replace("_CORPSE","")]))))
        changes["items"].append(dict(type=i["type"],blastRadius=i.get("blastRadius",int(1+(p-50)/30)),power=p))
        if i["type"]=="STR_CHRYSSALID_CORPSE":
            zombie=copy.deepcopy(i)
            zombie["blastRadius"]=changes["items"][-1]["blastRadius"]
            zombie["power"]=changes["items"][-1]["power"]
            zombie["type"]="STR_ZOMBIE_CORPSE"
changes["items"].append(zombie)     
mods["Suicide Aliens"]=changes
with the latest nightly build i finaly can do this:
newest mod: suicide bomb-aliens (explosion power/radius depends on strength of unit)
all aliens explode after death with enough strength to destroy most items/corpses - no loot!
if you can stun them you get your loot
are you up to the challenge?
rule file in 1. post
« Last Edit: April 28, 2014, 08:58:52 am by Falko »

Offline civilian

  • Colonel
  • ****
  • Posts: 154
    • View Profile
Re: Falko's Mod Collection-generating rulesets with python
« Reply #3 on: April 28, 2014, 11:12:46 am »
Nice!  8)

Offline Falko

  • Commander
  • *****
  • Posts: 802
    • View Profile
Re: Falko's Mod Collection-generating rulesets with python
« Reply #4 on: April 29, 2014, 07:39:53 am »
new mod
Variable alien armour
if you want to have a good reason to bring more than heavy plasma to the battle - this could do it
with this mod 4 of 5 (non terrorist)-aliens have an almost immunity (80% damage reduction) to plasma OR laser OR Highexplosives OR Armorpiercing damage
each rank has its own immunity - it is likely that you encounter all immunities in big ufos
even if you learned that floater-solder has plasma immunity .. that could change in the next ufo mission :)

rul file in first post

thanks goes to
Warboy "oh god what am i reading at" and SupSuper "what's on line 900" for the patience and help getting this done

PS:
yes i am aware that the rul file is bigger than the complete Xcom1Ruleset.rul file :D

Code: [Select]
changes=dict(alienRaces=[],units=[],armors=[],items=[],research=[],alienMissions=[],extraStrings=[])
atypes=[1,3,4,5]
armorchange=[0,1,2,1,1,1,2,2,2,0]
damagered=[1,1.05,1.1]
armorlist=[]
alienlist=[]
for u in orig["units"]:
    if u.get("race","") in alienraces:
        alienlist.append(u["type"])
        armorlist.append(u["armor"])
        for a in range(len(atypes)):
            changes["units"].append(copy.deepcopy(u))
            changes["units"][-1]["armor"]+="_RNGARMOUR_%s"%a
            changes["units"][-1]["type"]+="_RNGMEMBER_%s"%a           
armorlist=list(set(armorlist))
alienlist=list(set(alienlist))
for u in orig["armors"]:
    if u["type"] in armorlist:
        for a in range(len(atypes)):
            changes["armors"].append(copy.deepcopy(u))
            changes["armors"][-1]["type"]+="_RNGARMOUR_%s"%a
            changes["armors"][-1]["damageModifier"]=[]
            for ax in range(len(armorchange)):               
                axd=u["damageModifier"][ax]
                if ax==atypes[a]:
                    axd=axd*0.2
                else:
                    axd=axd*damagered[armorchange[ax]]
                changes["armors"][-1]["damageModifier"].append(axd)
for u in orig["items"]:
    if u["type"] in alienlist:
        for a in range(len(atypes)):
            changes["items"].append(copy.deepcopy(u))
            changes["items"][-1]["type"]+="_RNGMEMBER_%s"%a
for u in orig["research"]:
    if u["name"] in alienlist:
        for a in range(len(atypes)):
            changes["research"].append(copy.deepcopy(u))
            changes["research"][-1]["name"]+="_RNGMEMBER_%s"%a
    moredep=[]
    for d in u.get("dependencies",[]):
        if d in alienlist:
            for a in range(len(atypes)):
                moredep.append(d+"_RNGMEMBER_%s"%a)
    if moredep:
        changes["items"].append(dict(name=u["name"],dependencies=moredep))
for nrace in range(len(atypes)):   
    acount=nrace%len(atypes)   
    for race in orig["alienRaces"]:
        if not race["id"]in alienraces:continue
        racename=race["id"]+"_RNGRACE_%s"%nrace
        changes["alienRaces"].append(dict(id=racename,members=[]))
        for x in race["members"]:
            membername=x if x in terrorists else x+"_RNGMEMBER_%s"%acount
            changes["alienRaces"][-1]["members"].append(membername)
            acount=(acount+1)%len(atypes)
for u in orig["alienMissions"]:
    changes["alienMissions"].append(dict(type=u["type"],raceWeights={}))
    for w in u["raceWeights"]:
        changes["alienMissions"][-1]["raceWeights"][w]=dict()
        for race in u["raceWeights"][w]:
            if race in [x["id"] for x in orig["alienRaces"]]:
                countme=0
                if not race in alienraces:continue
                for nrace in range(len(atypes)):
                    addme=int(u["raceWeights"][w][race]/(len(atypes)+1))
                    countme+=addme
                    changes["alienMissions"][-1]["raceWeights"][w][race+"_RNGRACE_%s"%nrace]=addme
                countme+=addme
                changes["alienMissions"][-1]["raceWeights"][w][race]=addme+(int(u["raceWeights"][w][race])-countme)
for lng in lang:
    changes['extraStrings'].append(dict(type=lng,strings={}))
    for a in alienlist:
        for acount in range(len(atypes)):
            changes['extraStrings'][-1]['strings'][a+"_RNGMEMBER_%s"%acount]=lang[lng][lng][a]
    for race in alienraces:
       for acount in range(len(atypes)):
            changes['extraStrings'][-1]['strings'][race+"_RNGRACE_%s"%acount]=lang[lng][lng][race]
mods["Variable Alien Armour"]=changes
« Last Edit: April 29, 2014, 07:41:48 am by Falko »

Offline civilian

  • Colonel
  • ****
  • Posts: 154
    • View Profile
Re: Falko's Mod Collection-generating rulesets with python
« Reply #5 on: April 29, 2014, 11:20:55 am »
wow you are awesome! That variable armour mod is the first thing I will test when returning home!

Oh and here something I made BEFORE I discovered your Elerium-Recyling mod:
Code: [Select]
research:
  - name: STR_ELERIUM_PRODUCTION
    cost: 2000
    points: 100
    dependencies:
      - STR_SECTOPOD_CORPSE
      - STR_SECTOPOD_TERRORIST
      - STR_CYBERDISC_CORPSE
      - STR_CYBERDISC_TERRORIST
      - STR_NEW_FIGHTER_TRANSPORTER
manufacture:
  - name: STR_ELERIUM_115
    category: STR_EQUIPMENT
    requires:
      - STR_ELERIUM_PRODUCTION
    space: 6
    time: 300
    cost: 12500
ufopaedia:
  - id: STR_ELERIUM_PRODUCTION
    type_id: 5
    section: STR_WEAPONS_AND_EQUIPMENT
    requires:
      - STR_ELERIUM_PRODUCTION
    text: STR_ELERIUM_PRODUCTION_UFOPEDIA
extraStrings:
  - type: en-US
    strings:
      STR_ELERIUM_PRODUCTION: Elerium 115 Production
      STR_ELERIUM_PRODUCTION_UFOPEDIA: After researching the Sectopods and other vehicles thoroughly, we discovered by accident a way to produce Elerium 115, albeit only in small quantities and at a high price. Still, this could prove to be an invaluable discovery.
  - type: en-GB
    strings:
      STR_ELERIUM_PRODUCTION: Elerium 115 Production
      STR_ELERIUM_PRODUCTION_UFOPEDIA: After researching the Sectopods and other vehicles thoroughly, we discovered by accident a way to produce Elerium 115, albeit only in small quantities and at a high price. Still, this could prove to be an invaluable discovery.

 :)


Offline Falko

  • Commander
  • *****
  • Posts: 802
    • View Profile
Re: Falko's Mod Collection-generating rulesets with python
« Reply #6 on: April 30, 2014, 12:35:21 am »
a small mod : swap inventar hands
i found it always a bit confusing that the (left/right) handslot between inventar screen and battlescape were inverted with that mod i fix that
rul file in first post

Code: [Select]
changes=dict(invs=[])
invdata=dict([(x["id"],(x["x"],x["y"])) for x in orig["invs"]])
for bodypart in ["HAND","LEG","SHOULDER"]:
    changes["invs"].append(dict(id="STR_LEFT_"+bodypart,x=invdata["STR_RIGHT_"+bodypart][0],y=invdata["STR_RIGHT_"+bodypart][1]))
    changes["invs"].append(dict(id="STR_RIGHT_"+bodypart,x=invdata["STR_LEFT_"+bodypart][0],y=invdata["STR_RIGHT_"+bodypart][1]))
mods["Swap Inventar Hands"]=changes

Offline civilian

  • Colonel
  • ****
  • Posts: 154
    • View Profile
Re: Falko's Mod Collection-generating rulesets with python
« Reply #7 on: May 04, 2014, 12:33:32 pm »
The Break2Elerium mod is really great, I am using the low recovery version in my current campaign. Fianlly a use for all those clips WITHOUT making the feature overpowered. Excellent work, Falko!  :)

Offline Falko

  • Commander
  • *****
  • Posts: 802
    • View Profile
Re: Falko's Mod Collection-generating rulesets with python
« Reply #8 on: May 12, 2014, 10:38:44 pm »
dead soldiers give damaged armor
you can repair the armor (60% itemcost, 70%money/man hour costs)
or use it (with 65% armor values) (no visible difference) - if you die with a damaged armor nothing can be salvaged
file in the first post
Code: [Select]
changes=dict(armors=[],items=[],manufacture=[],extraStrings=[])
arlist={}
for a in orig["armors"]:
    if a.get("spriteInv","")!="" and a.get("corpseBattle",["STR_CORPSE"])[0]!="STR_CORPSE":
        arlist[a["type"].replace("_UC","")]=a["corpseBattle"][0]
        changes["armors"].append(dict(type=a["type"],corpseBattle=[a["type"].replace("_UC","")+"_REPAIRME"]))
        changes["armors"].append(copy.deepcopy(a))
        changes["armors"][-1]["type"]=a["type"].replace("_UC","")+"_REPAIRME"
        changes["armors"][-1]["storeItem"]=a["type"].replace("_UC","")+"_REPAIRME"
        for avalue in ["frontArmor","sideArmor","rearArmor","underArmor"]:
            changes["armors"][-1][avalue]=math.ceil(a[avalue]*0.65)
for i in orig["items"]:
    if i["type"] in list(set([arlist[x] for x in arlist])):
        for ar in arlist:
            if arlist[ar]==i["type"]:
                changes["items"].append(copy.deepcopy(i))
                changes["items"][-1]["type"]=ar+"_REPAIRME"
                changes["items"][-1]["recover"]=True               
for m in orig["manufacture"]:
    if m["name"] in arlist:
        mc=copy.deepcopy(m)
        mc["name"]=m["name"]+"_REPAIROP"
        for req in mc["requiredItems"]:
            mc["requiredItems"][req]=math.ceil(mc["requiredItems"][req]*0.6)
        mc["requiredItems"][m["name"]+"_REPAIRME"]=1
        mc["producedItems"]={m["name"]:1}
        for elem in ["time","cost","space"]:
            mc[elem]=math.ceil(mc[elem]*0.7)       
        changes["manufacture"].append(mc)
for lng in lang:
    changes['extraStrings'].append(dict(type=lng,strings={}))       
    for l in arlist:
        changes['extraStrings'][-1]['strings'][l+"_REPAIRME"]=lang[lng][lng]["STR_DAMAGE"]+"-"+lang[lng][lng][l]
        changes['extraStrings'][-1]['strings'][l+"_REPAIROP"]=lang[lng][lng]["STR_REPAIRS"]+": "+lang[lng][lng][l]
mods["Armor Repair"]=changes

Offline Avalanche

  • Sergeant
  • **
  • Posts: 49
    • View Profile
Re: Falko's Mod Collection-generating rulesets with python
« Reply #9 on: May 12, 2014, 10:56:28 pm »
I am very happy about the variable armor. I can't wait to test it out!

Offline Solarius Scorch

  • Global Moderator
  • Commander
  • *****
  • Posts: 11721
  • WE MUST DISSENT
    • View Profile
    • Nocturmal Productions modding studio website
Re: Falko's Mod Collection-generating rulesets with python
« Reply #10 on: May 12, 2014, 11:18:17 pm »
This one could really use new graphics.

Like a stained Personal Armour with one sleeve missing, or a half-burned Power Suit with a missing helmet and some holes... :)

Offline Falko

  • Commander
  • *****
  • Posts: 802
    • View Profile
Re: Falko's Mod Collection-generating rulesets with python
« Reply #11 on: May 12, 2014, 11:23:59 pm »
yes you are right now one can only see the difference in the stat values within the battlescape
but that's graphic work and i am a bit short on time (and xcom-graphic-knowledge) atm :(

Offline Solarius Scorch

  • Global Moderator
  • Commander
  • *****
  • Posts: 11721
  • WE MUST DISSENT
    • View Profile
    • Nocturmal Productions modding studio website
Re: Falko's Mod Collection-generating rulesets with python
« Reply #12 on: May 12, 2014, 11:37:12 pm »
yes you are right now one can only see the difference in the stat values within the battlescape
but that's graphic work and i am a bit short on time (and xcom-graphic-knowledge) atm :(

I know, it's not like I'm putting any weight on your shoulders. But if there's someone with enough time on their hands, it'd be awesome. :)

Offline Falko

  • Commander
  • *****
  • Posts: 802
    • View Profile
Re: Falko's Mod Collection-generating rulesets with python
« Reply #13 on: May 14, 2014, 06:33:47 pm »
i had an idea today how to fix the research-plasma as the one and only solution
the idea is this:
plasma weapons are getting the strengthApplied bonus
the strength of an user is added to the projectile damage
aliens: sectoid=30 - muton=70 strength
xcom: 20-40 at start capped at 70 strength
now next step: give the aliens +40 strength
now a plasma rifle in sectoid hands makes 30+40+80=150 damage!
now reduce the clip damage by 80: [("STR_HEAVY_PLASMA_CLIP",115-80),("STR_PLASMA_RIFLE_CLIP",80-80),("STR_PLASMA_PISTOL_CLIP",52-80)]
yes the pistol clip now has a negative -28 damage :)
NOW:
sectoid (the early aliens) can shoot with a bit less damage 30+40-80=-10 less damage than before
mutons (the badass soldier) can shoot with a bit more damage 70+40-80=+30 more damage than before

what about xcom?
rookies can get [20-40] strength resulting in:
heavy plasma=[20-40]+35(clip power)= [55-75] damage instead of 115, 70 strength capped=105 damage
plasma rifle=[20-40]+0(clip power)= [20-40] damage instead of 80, 70 strength capped=70 damage
plasma pistol=[20-40]-28(clip power)= [0-12] damage instead of 52, 70 strength capped=42 damage (no you dont get negative damage and you cant heal with low-strength-plasma-pistol-shots - i tried! :) )
i played a bit with these settings and quite like them
but i would really appreciate feedback on this

the code:
Code: [Select]
changes=dict(units=[],items=[])
for a in orig["units"]:
    if a.get("race","") in alienraces:
        changes["units"].append(dict(type=a["type"],stats=copy.deepcopy(a["stats"])))
        changes["units"][-1]["stats"]["strength"]=changes["units"][-1]["stats"]["strength"]+40
for t,p in [("STR_HEAVY_PLASMA_CLIP",115-80),("STR_PLASMA_RIFLE_CLIP",80-80),("STR_PLASMA_PISTOL_CLIP",52-80)]:
    changes["items"].append(dict(type=t,power=p,strengthApplied=True))
mods["PlasmaDownsize"]=changes

Offline Solarius Scorch

  • Global Moderator
  • Commander
  • *****
  • Posts: 11721
  • WE MUST DISSENT
    • View Profile
    • Nocturmal Productions modding studio website
Re: Falko's Mod Collection-generating rulesets with python
« Reply #14 on: May 14, 2014, 08:32:07 pm »
Falko, your mods are quite ingenious, clever and impressive. You have many ideas, and you're not afraid to realize them. It's very interesting to see them.

However, I feel that I need to say that very little of them can be considered seriously. I think it's a shame, really.