Contributing/Modding TW

From Era Wiki
< Contributing
Revision as of 14:27, 12 January 2023 by Vinumsabbathi (talk | contribs) (WIP)
Jump to: navigation, search

Era code is an absolute mess on the levels of Yandere Dev and is unlike most other programming languages. Most people who just want to add dialogue get stuck at the learning EraBasic phase and often lose motivation before they can put their ideas on the page. This book will teach the basics of EraBasic and guides you to be able to mod TW and make your own content.

The Language

Era games are made in EraBasic, a form of the BASIC programming language. It isn't a very advanced language like Lua or Ruby, but it's very easy to understand as a result

PRINT

EraBasic had a ton of commands just to output text which are all variations of the Print command.

PRINT

This outputs plain text in the current line without the ability to use expressions

PRINTFORM

PrintForm works like Print, but allows for in-line expressions with % and in-line IF statements using \@.

  • V - for numbers ({}); instead of "PRINTFORM {LOCAL}" you can write "PRINTFORMV LOCAL"

  • S - equivalent of strings (%%)

  • K - something with forcing kana (extremely rarely used)

  • D - ignores color change from SETCOLOR

  • L - makes line after printing the text

  • W - waits for player input

PRINT variants "S" or "V" should not be translated, they are for quick variable use without needing to write %% or {}

PRINTFORM Usage

String statements and expressions that return strings can be used with %% with the expression in the middle, and number expressions using {}.

LOCAL = 3

LOCALS = Tsukasa

PRINTFORML %LOCALS% has %LOCAL% cookies

Shortform IF statements can be used like this:

\@ ARG ? True # False \@

Putting [] and a number will turn the print statement into a button.

PRINTBUTTON can also be used if you don’t want to explicitly state the option ID. Keep in mind that you will have to wrap the text in “ and put the ID it corresponds with a comma between. Putting a @ before the string statement will also allow %% and {} to be used.

Conditional Statements

IF ARG >= 50

if ARG is greater than or equal 50

ELSEIF ARG == 20

if ARG equals 20

ELSE IF !ARG && !LOCAL

if there's r no ARG nor LOCAL

ELSEIF ARG < 10 || ARG = 69

if ARG is less than 10 or equal to 69

ELSE

every other condition

ENDIF

IF statements can also be nested inside other IF statements and loops.

A single line IF statement can also be used which does not need an ENDIF to end the statement but can only be used with one line instructions

SIF ARG > 10

PRINTFORM True!

Case statements can be used to define a range which determines which output is given from a input value

SELECTCASE ARG

CASE 0

ARG == 0

CASE 5 TO 10

ARG from 5 to 10

CASE 11, 15, 69

cases 11 15 and 69

CASE IS > 100

cases more than 100

CASEELSE

other cases

ENDSELECT

Loops

For loops are used to repeat a statement a certain amount of times, often manipulated by expressions.

FOR LOCAL, 0, 42

loop that will go from 0 to 42 (excluding 42)
LOCAL here is variable holding of current loop count

SIF LOCAL == 5

CONTINUE ;it skips case 5 and goes to next one - that is 6

stuff

SIF LOCAL == 12

BREAK ;exits the loop completely, ignoring whether it's the last time (42 in this case)

NEXT

While loops repeat infinitely until the condition is given

WHILE !LOCAL

this continues as long as LOCAL == 0

WEND

REPEAT is much like a FOR loop but does not allow for expressions

REPEAT 5

repeats itself 5 times
uses global variable COUNT for ... counting

REND

Changing Text Color

SETCOLOR 204, 0, 102 ;in rgb

SETCOLOR 0xff00ff ;in hex

SETCOLOR C_RED ;it also supports constant variables

SETCOLOR FOO("red") ;and functions

SETCOLORBYNAME Coral ;use HTML color names

RESETCOLOR ;use this when you're finished with fancy coloring

Comments

Comments can be used to disable execution of code or if you want to have comments about the code you are writing.

A single line can be commented out using ;

Do not translate jap comments, but feel free to make your own comments relating to the code so others can interpret what you are trying to do.

For multiple line comments use [SKIPSTART] before the code you want to comment out and [SKIPEND] at the line after the code you want to comment.

Variables

There are two types of variables in EraBasic, integers and strings. Integer values can only hold whole numbers while strings can only hold text or numbers converted to strings.

LOCAL and LOCALS (s for string) are always available, even outside of a function.

ARG and ARGS can be used inside of a function if it’s defined and needed.

MASTER and PLAYER refer to the player character

You can put :Number to differentiate between LOCAL and ARG values.

LOCAL = 1

LOCALS = Rotor

LOCAL:1 = 2000

LOCALS:1 = Andy

PRINTFORML %LOCALS:1% bought {LOCAL} %LOCALS% for %LOCAL:1%.

Andy bought 1 Rotor for 2000

#DIMs

Private variables have to be defined with #DIM or #DIMS at the start of the function

@CUMME(ARG, PleasureAmount)

  1. DIM PleasureAmount
  1. DIMS ItemName

DIM variables can also be saved to the character, the save, or saved globally.

DIM values are often preferred over CSVs as they do not take a numerical ID and are easier to merge

Functions

There are two types of functions, CALL functions and RETURN functions.

ARG, ARGS, LOCAL, LOCALS, and private variables can be defined in a function and can default to a certain value if an argument is not given

CALL Functions

Call functions are the default type of functions and require CALL before the function name to be executed.

CALL functions can call other CALL functions and RETURN functions

@UselessThing(ARG, ARG:1 = 0)

LOCAL = GetCum(ARG) ;Set result of a return function

CALL CanSex(ARG, ARG:1)

LOCAL:1 = RESULT ; set result of a call function

IF LOCAL:1

CALL StartUfufu(ARG, ARG:1)

RETURN 1 ;condition is true

ELSE

RETURN 0 ; return false

ENDIF

RETURN Functions

These functions are made to return an integer or a string and start with #FUNCTION or #FUNCTIONS depending on the return value.

They can only call other RETURN functions

@GetCum(ARG)

RETURN BASE:ARG:Cum ; returns the current value of the cum base

Operations

All operations are integer based

LOCAL ++ ; increases the value by one

LOCAL -- ; decreases value by one

LOCAL += 4 ; increases value by 4

LOCAL -= 6 ; decreases value by 6

LOCAL *= 3 ; multiplies value by 3

LOCAL /= 10 ; divides value by 10

LOCAL = LOCAL * 17 / 10 ; multiplies value by 1.7

Random

RAND is a function that rolls a number between 0 and the number given. Doing !RAND means that it’ll only proceed if it lands on 0. You can also do a custom number such as RAND(100), which rolls a number between 1 and 100

IF RAND(100) < 70

70% chance

SIF !RAND:4

25% chance

ENDIF

Character stats

A character is made up of multiple stats and data types, with most of them being in comma separated value sheets (CSVs).

There are many main data types for a character

  • ABL

  • BASE

  • CFLAG

  • CVAR

  • CSTR

  • EX

  • EXP

  • JUEL

  • MARK

  • SOURCE

  • STAIN

  • PALAM

  • TALENT

  • TCVAR

  • TEQUIP

  • DIM

    • CHARADATA

      • Charadata DIMs are weird and are going to be discussed in the variables section

    • CONST

    • DYNAMIC

    • GLOBAL

    • SAVEDATA

  • TempVar

ABL (Abilities)

ABLs are the character's abilities and can range from mundane stuff like speech, to a complicated scale like pee holding or alcohol resistance. They're found in CSV/ABL.csv

To grab:

ABL:CharaID:ID

they can also be grabbed with the internal name

ABL:CharaID:指

BASE

BASE are the character's stats/needs like their health, stamina, hunger, etc. Bases also have a character set max, known as a MAXBASE

They're found in CSV/BASE.csv

To grab:

BASE:CharaID:ID

they can also be grabbed with the internal name

BASE:CharaID:気力

CFLAG (Character Flags)

Flags that can be set in a per-character basis

They're found in CSV/CFLAG.csv

To grab:

CFLAG:CharaID:ID

they can also be grabbed with the internal name

CFLAG:CharaID:DiapeCharges

CSTR (Character Strings)

CSTRs are character separated strings, often used for keeping history when important things happen like losing a character's virginity.

They're found in CSV/CSTR.csv

To grab:

CSTR:CharaID:ID

they can also be grabbed with the internal name

CSTR:CharaID:LostVirginStr

EQUIP

Equipment the 2hu currently has. Usually used for clothing

They're found in CSV/TEQUIP.csv

To grab:

EQUIP:CharaID:ID

they can also be grabbed with the internal name

EQUIP:CharaID:Weapon

EX

EX values are used to determine how much of a certain event has happened during sex in a day.

NOWEX is also used as a way to track what's about to happen at the end of the command

They're found in CSV/EX.csv

To grab:

EX:CharaID:ID

they can also be grabbed with the internal name

EX:CharaID:VOrgasm

NOWEX:CharaID:ID

EXP (Experience)

EXP corresponds to certain things happening and is used to be checked to see if an ability can be leveled up. Often one action means one EXP for the related attributes

They're found in CSV/EXP.csv

To grab:

EXP:CharaID:ID

they can also be grabbed with the internal name

EXP:CharaID:VExp

JUEL (Gems)

JUELs are often combined with PALAM and EXP as a form of experience also used for commands and leveling up.

They're found in CSV/CFLAG.csv

To grab:

JUEL:CharaID:ID

they can also be grabbed with the internal name

JUEL:CharaID:Sex

MARK

MARKs are used to signify important events like if she's lewd or hates you.

They're found in CSV/MARK.csv

To grab:999

MARK:CharaID:ID

they can also be grabbed with the internal name

MARK:CharaID:Hate

SOURCE

Used to increase PALAM values and show it increasing.

They're found in CSV/SOURCE.csv

To grab:

SOURCE:CharaID:ID

they can also be grabbed with the internal name

SOURCE:CharaID:CPleas

STAIN

STAINs shows the dirtiness of the body part and if it has touched other parts.

Stains work on a bit based system

They're found in CSV/STAIN.csv

To grab:

= 16

PALAM (Parameters)

PALAMs are values that scale up with abilities and what commands you do. They're often used to track pleasure, lubrication, pain, etc.

They're found in CSV/PALAM.csv

To grab:

PALAM:CharaID:ID

they can also be grabbed with the internal name

PALAN:CharaID:Pain

TALENT

Character traits and skills

They're found in CSV/TALENT.csv

To grab:

TALENT:CharaID:ID

they can also be grabbed with the internal name

TALENT:CharaID:PeeHabit

TCVAR (Temporary Character Variables)

Used for per character temporary variables that are reset every day

They're found in CSV/TCVAR.csv

To grab:

TCVAR:CharaID:ID

they can also be grabbed with the internal name

TCVAR:CharaID:UnconTimer

TEQUIP

Equipment the 2hu currently has

Will clear at the end of the day much like TCVARs

They're found in CSV/TEQUIP.csv

To grab:

TEQUIP:CharaID:ID

they can also be grabbed with the internal name

TEQUIP:CharaID:VCombo

DIM DYNAMIC

DIM CHARADATA

These use the power of DIM variables to make a variable which can be any type. The main advantage of this is that it does not take a CSV ID and will never result in merge conflicts, making it perfect for mods

To grab:

Define on an ERH file
  1. DIM CHARADATA SAVEDATA PeopleFucked
means there are 5 entries which can be called per character
  1. DIM CHARADATA SAVEDATA ExtraThings, 5
To call in a ERB script

PeopleFucked:ARG:0

ExtraThings:ARG:0

ExtraThings:ARG:1

ExtraThings:ARG:2

ExtraThings:ARG:3

ExtraThings:ARG:4

DIM GLOBAL

These are flags that are GLOBAL and are not save-dependent.

To grab:

Define on an ERH file
  1. DIM GLOBAL nCumMultiply
To call in a ERB script

LOADGLOBAL

Adding Dialogue

Adding original dialogue is often the most common mod that people want to do, but the barrier due to the EraBasic language is often too much.

Grabbing Template Files

Assuming that we are adding dialogue to a character without dialogue, like Chimata as an example, we will have to grab the template files that are in the game.

Go to eraTW\改造とかしてみたい人のためのあれこれ\口上関連\別人版用口上テンプレ and grab the template files.

The minimum you should grab:

  • M_KOJO_KX_イベント

    • イベント (event) us is where Chimata says dialogue when you do commands

  • M_KOJO_KX_絶頂

    • 絶頂 (climax) is when chimata cums

  • M_KOJO_KX_コマンド

    • コマンド (command) is when you do a sex command to Chimata

These are optional but should be made if you want to complete a character

  • M_KOJO_KX_依頼

    • Deals with requests the 2hu gives to you

  • M_KOJO_KX_弾幕勝負

    • Deals with danmaku matches

  • M_KOJO_KX_COUNTER

    • Things the 2hu does after your command

  • M_KOJO_KX_愛撫コマンド

    • Reactions to caressing

  • M_KOJO_KX_

Finding the character

Then go to ERB/ 口上・メッセージ関連/個人口上/

and find your character in Japanese (use TouhouWiki.net or THB). When you find it, paste in the files and rename all files with X to your character ID (Chimata is 141, so replace it with K141).

Making Dialogue

Then use the PRINT commands to make dialogue that corresponds to the event (ie: Encounter is when you first meet her, COM_KX_300 is when you have a convo, 射精 is when the 2hu ejaculates).

Adding New Abilities

Adding a new ability is pretty complicated, especially since we are using CHARADATA DIMs instead of CSVs

In our example, we'll be adding an alcohol and drug resistance scale.

The DIM way

First we’ll have to define the variables that we will use for our ability.

Make a new ERH file (or use an existing file if you already created some stuff), and add this

  1. DIM CHARADATA SAVEDATA AlcoholResistance
  1. DIM CHARADATA SAVEDATA DrinkingExp

AlcoholResistance is our ability, and DrinkingExp is our experience. These will be applied to each character and saved to the save file

Then we’ll have to add the ability to level up and down this stat, as well as state the amount of experience needed to level up this ability.

After making the ability, it's time to make it show up on the user interface. Since this is a scale attribute, we will also have to make a new grading system for it.

Most of our work is based off modifying TRANSLATION/List.erb

Our first modification is to edit PRINT_SPECIFIC_HTML to show our new ability we just added.

  1. DIM CONST DISP_ID =

0, 9, 43, 0, 50, 15, 31,

1, 10, 41, 1, 54, 16, 32,

2, 11, 42, 2, 55, 17, 33,

3, 12, 40, 3, 52, 18, 34,

4, 13, 44, 4, 51, 0, 35,

5, 14, 45, 0, 53, 0, 30,

0, 0, 46, 0, 0, 0, 0,

0, 0, 47, 0, 0, 0, 0,

0, 0, 48, 0, 0, 0, 23,

0, 0, 49, 0, 0, 0, 0,

}

  1. DIM C_ID

{

  1. DIMS CONST DISP_NAME =

" PAIN", " Intimacy", "Knowledge", "CSens", " Hand", " Maso", " Semen",

" PLSR", "Obedience", " Speech", "VSens", "Vagina", " Sado", " Homo♀",

" LEWD", " Desire", " Combat", "ASens", " Anus", "Homo♀", " Homo♂",

" HATE", "Technique", " Cleaning", "BSens", " Chest", "Homo♂", " Creampie",

"Old HATE", "Servitude", " Cooking", "MSens", "Tongue", "", " A Creampie",

" RAPE", " Exposure", " Music", "", " Waist", "", "Masturbation",

"", "", " Logging", "", "", "", "",

"", "", " Fishing", "", "", "", "",

"", "", " Foraging", "", "", "", "Drug",

"", "", " Mixing", "", "", "", "",

}

This makes it show up on the gui but we still have to sort out the grading system

Since we are making an attribute that is a scale we will have to make a new grading system for it.

ELSEIF ARG == 54

OUTPUT '= @"<nonbutton title='%ABILITY_DESCRIPTION_HTML(C_ID,ARG)%'>"

OUTPUT += @"%DISP_NAME:ARG, 10%:"

OUTPUT += PRINT_RANK_HTML(AlcoholResistance:C_ID:0, "MAX_11_SCALE")

OUTPUT += @" {ABL:C_ID:(DISP_ID:ARG), 3}"

OUTPUT += @"</nonbutton>"

This makes it show the level of alcohol resistance

In PRINT_ALPHABET_HTML, we will have to define the ranks for our new scale. Make sure to do the same thing in PRING_ALPHABET too in COMMON.erb

  1. DIMS CONST STR_RANK11, 11 = "Ex", "SS", " S", " A", " B", " C", " D", " E", " F", " G", " H"
this makes C the average and turns it grey

{

  1. DIMS CONST C_RANK11, 11 =

"C_P_PURPLE", "C_WHITE", "C_RED", "C_ORANGE", "C_YELLOW",

"C_GRAY", "C_YELLOW", "C_ORANGE", "C_RED", "C_WHITE", "C_PINK"

}

Define a new entry for 11 ranks

SELECTCASE RANK_NUM

CASE 11

RETURNF COLOR_PRINT_HTML(STR_RANK11:RANK, C_RANK11:RANK, 2)

Under CALC_RANK_FUNCTION and CALC_RANK (in COMMON.erb) we can define what our numbers scale to. In our case we will be doing a -5 to 5 system

CASE "MAX_11_SCALE"

for endurance scales

SELECTCASE VAR_VALUE

CASE IS >= 5

RANK = 0

upper limit

CASE IS >= 4

RANK = 1

CASE IS >= 3

RANK = 2

CASE IS >= 2

RANK = 3

CASE IS >= 1

RANK = 4

CASE IS >= 0

RANK = 5

you start at 0

CASE IS >= -1

RANK = 6

CASE IS >= -2

RANK = 7

CASE IS >= -3

RANK = 8

CASE IS >= -4

RANK = 9

CASEELSE

RANK = 10

lower limit

ENDSELECT

Define an entry in CALC_RANK_NUM_FUNCTION

CASE "MAX_11_SCALE"

needed for endurance abilities

RANK_NUM = 11

Make a description to show criteria for level up

CASE 54; Alcohol Resistance

LOCALS '= "How strong drugs affect you.\n"

LOCALS += "Progress towards next stage (addict):\n"

IF AlcoholResistance:C_ID:0 >= 5

LOCALS += @" MAXED!\n"

ELSE

LOCALS += "Experience:\n"

LOCALS += @" Drug: %ABILITY_FORMAT_HTML(OrgasmDenyExp:C_ID:0, EXP_DEMAND_22(0,90,C_ID,1))%\n"

ENDIF

LOCALS += "Progress towards next stage (nondrinker):\n"

IF AlcoholResistance:C_ID:0 <= -5

LOCALS += @" MAXED!"

ELSE

LOCALS += "Experience:\n"

LOCALS += @" Drug: %ABILITY_FORMAT_HTML(DrinkingExp:C_ID:0, -EXP_DEMAND_22(0,90,C_ID))%"

ENDIF

Go to ERB/ステータス計算関/ABL/ABL_UP_DATA.ERB and add the id of the exp you want to occupy under EXP_DEMAND.

In this case, we will be taking ID 22.

ELSEIF ARG == 22

call exp demand for alcohol resistance

RETURNF EXP_DEMAND_22(ARG:1,ARG:2,ARG:3)

Once we did that, we will have to make the function that we wanted to call

≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
Alcohol and Drug Resistance
For these values they determine the threshold
≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡

@EXP_DEMAND_22(ARG,ARG:1,ARG:2,ARG:3=0,ARG:4=0)

  1. FUNCTION

VARSET LOCAL

reset local since this is our grab variable

IF !ARG:4

LOCAL = AlcoholResistance:(ARG:2):0+(ARG:3)

set the grab variable to the 2hu's alcohol resist

ELSE

LOCAL = ARG:4

ENDIF

grab the exp needed based off the level

SELECTCASE LOCAL

CASE -5

LOCAL = -2000

CASE -4

LOCAL = -1000

CASE -3

LOCAL = -500

CASE -2

LOCAL = -250

CASE -1

LOCAL = -100

CASE 0

LOCAL = 0

CASE 1

LOCAL = 100

CASE 2

LOCAL = 250

CASE 3

LOCAL = 500

CASE 4

LOCAL = 1000

CASE 5

LOCAL = 2000

ENDSELECT

RETURNF LOCAL

This will give the exp needed to level up or down the ability.

Next up is a way of giving experience to this stat. Since our example is alcohol resistance, it would be a good call to increase it by drinking alcohol

In COM332, we can add a line below line 181 which gives alcohol resistance if the 2hu drinks alcohol

SOURCE:歓楽 = SOURCE:歓楽 * 味補正 / 10

SOURCE:征服 = SOURCE:征服 * 味補正 / 10

SOURCE:受動 = SOURCE:受動 * 味補正 / 10

custom code

DrinkingExp:TARGET:0 += 味補正

Finally is a way to track if a character has enough exp to level up this stat. The function for this is found in

Alcohol resistance

LOCAL:90 = AlcoholResistance:ARG:0

IF DrinkingExp:ARG:0 >= EXP_DEMAND_22(0,90,ARG,1) && AlcoholResistance:ARG:0 < 5

AlcoholResistance:ARG:0 ++

IF ARG == 0

PRINTFORMW %PARSE("Your")% body is now more resiliant to drugs.

ELSE

PRINTFORMW %CALLNAME:ARG%'s body is now more resiliant to drugs.

ENDIF

ELSEIF (DrinkingExp:ARG:0 < (EXP_DEMAND_22(0,90,ARG,-1)) || (DrinkingExp:ARG:0 < EXP_DEMAND_22(0,90,ARG) && DrinkingExp:ARG:0 > 0)) && AlcoholResistance:ARG:0 > -5

AlcoholResistance:ARG:0 --

IF ARG == 0

PRINTFORMW %PARSE("Your")% body is now less resiliant to drugs.

ELSE

PRINTFORMW %CALLNAME:ARG%'s body is now less resiliant to drugs.

ENDIF

ENDIF

You can add additional talents on level up like I've did on my orgasm denial scale but you don't have to

Adding Items

Adding new items is easy, but it requires editing CSVs, adding the entry into ITEMDATA.erb, and applying its effects in Add_Item.erb

In our example, we will be making a candy which increases V and V stretch Exp by 100, takes our virginity, and increase stamina by 1000

First, we'll have to go to Item.csv and add our item and set it's ID

330,UselessCandy,3000

This makes an item with an ID of 330 which costs 500 yen.

Then we'll have to go to ERB/Translation/STR.erb and go to ITEMNAME_TR. Below that function, we can insert our translated item name.

CASE 70

translated name which corresponds to our item id

LOCALS = Violet Candy

We will also have to add a description to the item in ERB/アイテム解説.erb under ITEM_EXPLANATION to tell the player what it does.

CASE 330

RETURNF "Drug that instantly removes【Virgin】from someone and stretches their holes. Immediate effect use item."

Once we added the item ID and its name, we'll have to add it to SHOP関連/ITEMDATA.erb to make it a buyable item and to categorize it correctly

CASE "UselessCandy"

SELECTCASE ARGS

CASE "SALES"

how many you can buy

RETURN 99

CASE "購入"

behavior when purchasing

CALL ITEM_MATOMEGAI(ARG, ARG:1)

CASE "TYPE:消耗品", "SHOP:通信販売"

item flags

RETURN 1

ENDSELECT

This categorizes it as a consumable that is buyable in mail order.

Adding effects to items

Finally, we get to applying the item's effects. Go to TRANSLATION/Addition/Add_Item.erb and make it available to use by putting it under Add_UseableItem

CASE 330

RETURN 2

add your item's effects under Add_UseItem

CASE 330

PRINTFORMW You pull out a large jawbreaker, put it in your mouth, and start sucking on it.

PRINTFORMW It tastes like strawberry.

PRINTFORML While you are enjoying your candy, a portal appears underneath you.

PRINTFORMW A foriegn object shifts your %CLOTHES_TR(PANTSNAME(EQUIP:ARG:下半身下着2, ARG))% and inserts it in your \@ HAS_VAGINA(MASTER) ? %FSYN("vagina")+" and"%#\@ %FSYN("anus")%...

IF TALENT:MASTER:処女

if player has a vag and is a virgin

SETCOLOR 247,171,166

PRINTFORMW 【Virginity Loss】

CALL SET_HISTORY_LOST_V(MASTER, 26, "ペニス",)

RESETCOLOR

TALENT:MASTER:処女 = -1

take master's virginity by yukari's tentacles

PRINTFORMW You feel an unbearable pain in your %FSYN("vagina")%, getting violated like it's nothing.

ENDIF

IF CSTR:MASTER:アナル処女喪失履歴 == ""

if player is a anal virgin

SETCOLOR 247,171,166

PRINTFORMW 【Anal Virginity Loss】

CALL SET_HISTORY_LOST_A(MASTER, 26, "ペニス",)

RESETCOLOR

take master's virginity by yukari's tentacles

PRINTFORMW Your asshole bleeds profusely from the sudden insertion.

ENDIF

PRINTFORMW You try to scream, but the candy has gagged your mouth shut…

PRITNFORMW You look down and it seems to be a wide tenticle that's fucking you.

PRINTFORMW You attempt to resist the tentacles violating you, but it doesn't budge.

PRINTFORNW The relentless sensation is too much to endure as you fall on your ass…

PRINTFORMW You surrender in pleasure as you cum over and over…

EXP:MASTER:異常経験 += 30

IF HAS_VAGINA(MASTER)

EXP:MASTER:V経験 += 100

EXP:MASTER:V拡張経験 += 100

EXP:MASTER:絶頂経験 += 15

EXP:MASTER:V絶頂経験 += 15

ENDIF

ENDIF

PRINTFORNW This repeats for hours…

PRINTFORMW The tenticles never stops fucking you, despite you fainting…

CFLAG:MASTER:徹夜 = 1

CFLAG:MASTER:ヤラせちゃった = 1

RETURN 2

give V experience, climax, and rape flag and end day.

Adding new commands

Adding a new command is a bit complicated and can get overboard very quickly as you'll have to add them to the user interface and make a message

For this example, we'll be making a command that kicks out the selected 2hu from the room we are in.

First off, we have to add our command in CSV/Train.csv to register it as a usable command.

489,KickOut

Once we've done that, we can add the command to the user interface

First we'll have to add the generic name to the command in TRANSLATION/STR.erb

CASE 489

LOCALS = Kick Out

Once we have added the generic name of the command, we can now add the name that will be shown in the actual user interface in ERB/コマンド関連/USERCOM_コマンド表示処理.ERB under the SHOW_USERCOM function

ELSEIF LOCAL == 489

PRINTFORMC Kick Out %CALLNAME:TARGET%[{LOCAL,3}]

This will tell the name of the character we are about to kick out of our room.

The final steps involve making our command. Make a new ERB file anywhere in the ERB folder (but you should make your own folder if you are adding new commands and such). Name it something like "COMF{ID} Command Name" ("COMF489 Kick Out" in our case)

Open the new ERB file we just created. First, we make the function that give the command it's effects

@COM489

CFLAG:TARGET:好感度 -= (50 - ABL:TARGET:親密 * 2)

CFLAG:TARGET:信頼度 -= (50 - ABL:TARGET:親密 * 2)

reduce favor and reliability

SOURCE:TARGET:反感 += 300

BASE:TARGET:怒り += (5500 - ABL:TARGET:親密 * 100)

make 2hu mad

CFLAG:TARGET:現在位置 = KICKOUT()

move the 2hu to a different room

RETURN 1

After that, give the player a description of what they do to do that action.

@MESSAGE_COM489

PRINTFORMDW You kick %CALLNAME:TARGET% out of %STR_TR(CFLAG:MASTER:現在位置+8000)%

RETURN 1

Finally are the conditions that restrict the use of the command

@COM_ABLE489

Do not allow during ufufu or time stop

SIF FLAG:70 == 1

RETURN 0

SIF CFLAG:うふふ != 0

RETURN 0

SIF !TFLAG:100

RETURN 0

SIF CFLAG:睡眠

RETURN 0

SIF TARGET == MASTER ; doesn't make sense to kick yourself out

RETURN 0

RETURN 1

Adding Underwear

Underwear isn’t something you need to add more of unless you want to make unique underwear or went full AB mode and decide to add diapes to gensokyo (me).

Underwear can be added by using the code as a template. It will automatically add them to the underwear array where all 2hus can wear

ID is your underwear ID
the english O_DATA entries are for my branch only

@EXIST_下半身下着_ずらし可能ID

  1. LOCALSIZE 1
  1. LOCALSSIZE 1

@下半身下着_ずらし可能ID(ARG, O_DATA, V_NAME)

  1. FUNCTION
  1. LOCALSIZE 1
  1. LOCALSSIZE 1
  1. DIMS O_DATA
  1. DIMS V_NAME

SELECTCASE O_DATA

CASE "名前"

name

CALLF MAKE_STR(V_NAME, "diaper")

CASE "描写"

description variable
the real description is in MISC.ERB(?)

CALLF MAKE_STR(V_NAME, "wtf is this used for")

CASE "透ける(前)"

can you see from the front

CALLF MAKE_INT(V_NAME, 0)

CASE "透ける(後)"

can you see from the back

CALLF MAKE_INT(V_NAME, 0)

CASE "はける"

requirements to have the 2hu wear it

IF !nOmutsu

the diaper flag

CALLF MAKE_INT(V_NAME, 0)

ELSEIF PeeHold:ARG:0 <= -2 || PooHold:ARG:0 <= -2 || TALENT:ARG:幼児/幼児退行 || GETBIT(TALENT:ARG:OmoGuardian, 2) || TALENT:ARG:BladderSize == 2

needs to have continence issues or be a AB (infant regression) or DL (padded legend)

CALLF MAKE_INT(V_NAME, 1)

ENDIF

CASE "着せ替え可能"

can change into it after having their panties/diaper pilfered

CALLF MAKE_INT(V_NAME, 1)

CASE "関連下着"

matching upperwear

CALLF MAKE_INT(V_NAME, CLOTHES_ID("上半身下着1", "Tシャツ"))

CASE "Priority"

gives a priority (re
second chance) roll that it’ll be picked.
from 0 to 100. 100 means it WILL be picked if the game rolls on it and fails the RNG check for other panties.

CALLF MAKE_INT(V_NAME, 100)

CASE "Unisex"

can men wear it

CALLF MAKE_INT(V_NAME, 1)

CASE “Panties Type”

[SKIPSTART]

Types:

・Underwear

・Open-Crotch

・Pull-Up

・Diaper

・Naked/Bare Skin

Catheters and incontinence/menstrual/diaper booster pads are handled with CFLAGs

Use IsPadded(ARG) to find out if the 2hu has a diaper or a pad.

[SKIPEND]

CALLF MAKE_STR(V_NAME, "Diaper")

CASE “Pee Capacity”

how much piss it can hold if pee accidents are enabled
if the 2hu has an accident without being padded they get dirty PALAMs (bad). If you’re the one that has an accident you get the 「Not Potty Trained」 reputation

CALLF MAKE_INT(V_NAME, 1750)

CASE “Poo Capacity”

how much poop it can contain if messy accidents are enabled

CALLF MAKE_INT(V_NAME, 1000)

CASE “Armor”

how much penetration it can stop

CALLF MAKE_INT(V_NAME, 2)

CASE “Armor Health”

how much damage can the armor take before losing efficiency or breaking

CALLF MAKE_INT(V_NAME, 650)

CASE “Armor Coverage”

how much damage can the armor take before losing efficiency or breaking

CALLF MAKE_INT(V_NAME, 650)

CASE "コレクション解禁条件"

CALLF MAKE_STR(V_NAME, "Req: Potty Training -2")

CASE "コレクション表示可能"

CALLF MAKE_INT(V_NAME, 1)

ENDSELECT

Adding Weapons

Weapons can be added by using the code as a template. It will automatically add them to the weapon array where all 2hus can equip if Postal mode is on

ID is your weapon ID

@EXIST_WeaponID

  1. LOCALSIZE 1
  1. LOCALSSIZE 1
オブジェクト本体

@WeaponID(ARG, O_DATA, V_NAME)

  1. FUNCTION
  1. LOCALSIZE 1
  1. LOCALSSIZE 1
  1. DIMS O_DATA
  1. DIMS V_NAME

SELECTCASE O_DATA

CASE "名前"

CALLF MAKE_STR(V_NAME, "SIG MCX VIRTUS")

CASE "FullName"

CALLF MAKE_STR(V_NAME, "Sig Sauer MCX VIRTUS Assault Rifle")

CASE "描写"

CALLF MAKE_STR(V_NAME, "This is your weapon description")

CASE "装備部位"

CALLF MAKE_STR(V_NAME, "「Weapon」")

CASE "Damage"

default damage in a normal hit

LOCAL = 962

CALLF MAKE_INT(V_NAME, LOCAL)

CASE "Accuracy"

chance to HIT, 0-100%

LOCAL = 50

CALLF MAKE_INT(V_NAME, LOCAL)

CASE "Burst"

how many shots it fires per turn

LOCAL = 5

CALLF MAKE_INT(V_NAME, LOCAL)

CASE "Pellets"

bullets per shot

LOCAL = 1

CALLF MAKE_INT(V_NAME, LOCAL)

CASE "Loudness"

how far away a shot can be heard (in units)

LOCAL = 7

CALLF MAKE_INT(V_NAME, LOCAL)

CASE "Mag Size"

shots until you need to reload

LOCAL = 30

CALLF MAKE_INT(V_NAME, LOCAL)

CASE "Range"

how many units the weapon can fire

LOCAL = 5

CALLF MAKE_INT(V_NAME, LOCAL)

CASE "Penetration"

units that you can see it can penetrate
also dictates what armor it can go through

LOCAL = 2

CALLF MAKE_INT(V_NAME, LOCAL)

CASE "Grade"

how many times you have to give 100 charisma to the kappa

LOCAL = 5

CALLF MAKE_INT(V_NAME, LOCAL)

CASE "Price"

price to DEVELOP

LOCAL = 470000

CALLF MAKE_INT(V_NAME, LOCAL)

CASE "Prerequisite"

weapon required to develop first

LOCAL = 40

CALLF MAKE_INT(V_NAME, LOCAL)

These are attachment slots

CASE "Grip Slot"

LOCAL = 1

CALLF MAKE_INT(V_NAME, LOCAL)

CASE "Foregrip Slot"

LOCAL = 1

CALLF MAKE_INT(V_NAME, LOCAL)

CASE "Reciever Slot"

LOCAL = 1

CALLF MAKE_INT(V_NAME, LOCAL)

CASE "Magazine Slot"

LOCAL = 1

CALLF MAKE_INT(V_NAME, LOCAL)

CASE "Barrel Slot"

LOCAL = 1

CALLF MAKE_INT(V_NAME, LOCAL)

CASE "Tactical Slot"

LOCAL = 1

CALLF MAKE_INT(V_NAME, LOCAL)

CASE "Sight Slot"

LOCAL = 3

CALLF MAKE_INT(V_NAME, LOCAL)

CASE "Stock Slot"

LOCAL = 1

CALLF MAKE_INT(V_NAME, LOCAL)

CASE "Type"

[SKIPSTART]

Types:

・Melee

・Firearm

・Explosive

・Throwable

[SKIPEND]

CALLF MAKE_STR(V_NAME, "Firearm")

CASE "Class"

[SKIPSTART]

Types:

・Pistol

・Rifle

・Shotgun

・Light Machine Gun

・Medium Machine Gun

・Heavy Machine Gun

・1H Blunt

・2H Blunt

・1H Blade

・2H Blade

・Spear

[SKIPEND]

CALLF MAKE_STR(V_NAME, "Rifle")

CASE "Ammo"

[SKIPSTART]

Caliber in metric units

[SKIPEND]

CALLF MAKE_STR(V_NAME, "5.56x45mm")

CASE "Fire Sound"

CALLF MAKE_STR(V_NAME, "firearms/AT MR-92.wav")

ENDSELECT

Adding New Characters

Adding characters requires a CSV entry, a CHARADATA ERB file, and a picture associated with them

This is a character’s CSV entry (place in the CSV folder

charcter ID

番号,145,

character name

名前,Kotohime,

character callname

呼び名,Kotohime,

max stamina

基礎,体力,2500

max energy

基礎,気力,2000

don’t touch

基礎,勃起,1500

maybe touch if your 2hu has a dick

基礎,精力,10000

基礎,法力,1000

基礎,ムード,1500

基礎,理性,1000

基礎,怒り,1000

基礎,仕事量,0

基礎,深度,2000

基礎,酒気,1500

max bladder and bowels are handled in PeeStuffs.ERB so don’t set them here
same with body part health and hypno things
is virgin or not

素質,処女,0

sex (1 = girl, 2 = boy, 3 = futa, 7 = andro)

素質,性別,1

traits

素質,性的興味,1;好奇心

素質,態度,-1; Docile

素質,無関心,1;aphathethic

素質,陽気/陰気,-1;陽気

素質,貞操,1;virtuous

素質,倒錯的,1;perverted

素質,性別嗜好,-1;両刀

素質,中毒しやすい,1;easily addicted

素質,絶倫,1

素質,C感度,1; c sensitive

素質,バストサイズ,-1;small bewbs

素質,サド,1;sadist

素質,人間,1;human

abilities

能力,清掃技能,1;cleaning

能力,話術技能,0;speech

能力,戦闘能力,3;combat

能力,教養,0;knowledge

能力,料理技能,0;cooking

能力,音楽技能,0;music

素質,伐採Lv,0;logging

素質,釣りLv,0;fishing

素質,採集Lv,0;foraging

素質,調合Lv,0;mixing

sex abilities

能力,C感覚,2

能力,A感覚,1

能力,B感覚,1

能力,欲望,2

能力,レズっ気,2

能力,サドっ気,3

flags

フラグ,地位,1000;地位

starting location

フラグ,初期位置,242

wake up hours

フラグ,起床時間,420;7時

visiting hours

フラグ,来訪時間,540;9時

going home

フラグ,帰宅時間,1080;18時

sleeping

フラグ,就寝時間,1320;22時

favorite place to visit

フラグ,よく行く地域,-1; stay

general location

フラグ,自宅位置,270;kotohime's room

フラグ,移動率補正,

フラグ,移動節度,0

type of maternity leave

フラグ,産休タイプ,2;60日目から休む

personality

フラグ,口調,2

相性,
work info

CSTR,仕事情報,Patrolling the Village every morning 06:00~12:00

CSTR,職場,Village - Square

title

CSTR,10,~Princess Dreaming of Beauty in Danmaku~ ●Race:Human

フラグ,産休タイプ,

Then the CHARADATA file can be copied from another place and then pasted to your modded ERB folder.

Character movement data

@CHARAMOVE_DATA_145(ARG, ARG:2)

LOCAL = 145

SELECTCASE ARG

連動設定(RETURN=依存するキャラ, RESULT
1~3=対等に連動するキャラ)

CASE 1

特殊生活時間設定(CFLAG
LOCAL:生活時間補正を設定する)
2hus the 2hu likes to go with

RESULT:1 = アリス

RESULT:2 = Shanghai

RESULT:3 = Hourai

CASE 3

Frequency(±~10=More frequently goes to/Goes to less frequently, -100=Will never go)

CASE 4

SELECTCASE ARG:2

Places that the 2hu likes to go to

CASE P232蓮子の部屋, P233メリーの部屋, P202中央広場

RETURN 5

Places the 2hu will never go

CASE P221稗田邸, P224慧音宅, P222寺子屋, P226小鈴私室, P229阿求私室

RETURN -100

CASE P208雷鼓の部屋, P209八橋の部屋, P210弁々の部屋

RETURN -100

CASE P231蛮奇の部屋, P234ユキの部屋, P235マイの部屋, P239美宵の部屋

RETURN -100

ENDSELECT

Places the 2hu can go out

CASE 7

SELECTCASE ARG:2

CASE 桜並木の鳥居, 神社境内, 神社本堂, 神社縁側, 夢幻遺跡

RETURN 1

CASE お地蔵通り, 枝垂れ柳の下, 命蓮寺境内, 墓地, 神霊廟広場

RETURN 1

CASE 広場, 商家町, 呑屋小道, 長屋街

RETURN 1

CASE 竹林入り口, 迷いの小道, 斜角の竹林, 兎の洞穴, 無名の丘, 太陽の畑

RETURN 1

CASE 中有の道, 三途の川

RETURN 1

ENDSELECT

引力設定

CASE 8

ENDSELECT

@EXIST_キャラデータ145

  1. LOCALSIZE 1
  1. LOCALSSIZE 1

@キャラデータ145(ARG, O_DATA, V_NAME)

  1. FUNCTION
  1. LOCALSIZE 1
  1. LOCALSSIZE 1
  1. DIMS O_DATA
  1. DIMS V_NAME

SELECTCASE O_DATA

CASE "呼び名"

Callname

CALLF MAKE_STR(V_NAME, "Kotohime")

こっから衣装設定

CASE "今日のパジャマ"

Pajama set

CALLF MAKE_STR(V_NAME, "パジャマ(ワンピース)セット")

Day Clothing

CASE "普段着:着物"

Kimono

CALLF MAKE_INT(V_NAME, CLOTHES_ID("着物", "着物"))

CASE "普段着:上半身上着1"

Upper wear

CALLF MAKE_INT(V_NAME, CLOTHES_ID("上半身上着1", "上着"))

CASE "普段着:その他1"

Accessory

CALLF MAKE_INT(V_NAME, CLOTHES_ID("その他1", "リボン"))

CASE "普段着:靴"

Shoes

CALLF MAKE_INT(V_NAME, CLOTHES_ID("靴", "靴"))

CASE "普段着:靴下"

Socks

CALLF MAKE_INT(V_NAME, CLOTHES_ID("靴下", "靴下"))

Unique Underwear

CASE "固有下着形容詞"

CALLF MAKE_STR(V_NAME, "rabbit printed")

CASE "固有下半身下着名"

CALLF MAKE_STR(V_NAME, "princess panties")

Unique Bra

CASE "固有上半身下着"

CALLF MAKE_INT(V_NAME, 1)

CASE "固有上半身下着名"

CALLF MAKE_STR(V_NAME, "princess bra")

Chance of wearing unique panties

CASE "固有下着着用条件"

SIF !RAND:(3 - (2 * 勝負下着判定(Kotohime)))

CALLF MAKE_INT(V_NAME, 1)

Panties Properties

CASE "固有下着透ける(前)"

CALLF MAKE_INT(V_NAME, 0)

CASE "固有下着透ける(後)"

CALLF MAKE_INT(V_NAME, 0)

CASE "固有下着生地厚さ"

CALLF MAKE_INT(V_NAME, 3)

料理関連
Tastes

CASE "料理:好きな味"

CALLF MAKE_STR(V_NAME, "精妙/" * 5 + "ふわふわ/" * 2 + "パイ/" * 2 + "サクサク/" * 3 + "揚げ物/" * 5 + "しょっぱい/" * 5 + "絢爛/" * 2 + "高級食材/" * 10 )

CASE "料理:嫌いな味"

CALLF MAKE_STR(V_NAME, "葉物/" * 2 + "すっぱい/" * 5 + "果物/" * 3 + "辛い辛い/" * 8 + "安物食材/" * 10 )

CASE "料理:助手効果"

CALLF MAKE_STR(V_NAME, "精妙/")

贈り物関連
Gift preferences

CASE "感性:好き"

CALLF MAKE_STR(V_NAME, "高級/金/かわいい/オシャレ/" + "宝石/" * 5 + "黄金の/" * 3)

CASE "感性:嫌い"

CALLF MAKE_STR(V_NAME, "奇妙/" + "安物/" * 3 + "妖力/グロテスク/" * 10)

ENDSELECT

-------------------------------------------------
固有料理設定
DISH_NAME 料理名
RESULTS 料理の種類(軽食/主食/デザート)
CALL 材料設定("") 材料の指定。"汎用"を入れると自動で汎用食材になる
DISH_TASTE 味の設定
DISH_COMMENT (任意)一行コメント
DISH_TIME (任意)調理にかかる時間
DISH_MAXLIMIT (任意)料理の持続時間
-------------------------------------------------
Unique Food

@SPECIAL_MENU_145

DISH_NAME = Chicken Pot Pie

RESULTS = 主食

CALL 材料設定("汎用")

DISH_TASTE = 精妙/ふわふわ/パイ/サクサク/しょっぱい/肉料理/野菜抜き/

DISH_COMMENT = A savory pie with chicken inside. No vegetables though.

RETURN 1

Diary Entries

In a nutshell: first you write a diary entry under `@DIARY_TEXT_KXX`, like so:

※PAGENUM
0は使えません

SELECTCASE PAGENUM

CASE 1

PRINTFORML Well, I finally did it. I bought myself a diary.

PRINTFORML Although I suppose it's more like a journal. What would I even write in a normal diary?

PRINTFORML 「Nothing much happened on the bridge today. Went out drinking with Yuugi. Wanted to confess to her but didn't.」

PRINTFORML 「Saw a bunch of people I was jealous of. Went home and seethed for a while. Paruparuparuparu.」

PRINTFORML 「I hate myself.」

PRINTFORML It would just be the same things over and over. No, I'm going to use this to blow off steam.

PRINTFORML My anger, my jealousy, my self-hatred... I'm going to write about it here. Maybe it'll make me feel better.

PRINTFORML At least I won't be burdening anyone else with my insufferable whining.

Then you set the conditions for it to show up in @DIARY_BEFORE_CHECK_KXX:

Before she meets the player

IF DIARY:パルスィ:1 == 0

DIARY:パルスィ:1 = 3

CALL CHARA_DIARY_PAGESETTING(パルスィ, 1)

ENDIF

You can do other, more complicated requirements:

"I don't know what I believe anymore" (Req
200+ Favorability)

IF DIARY:パルスィ:7 == 0 && CFLAG:パルスィ:好感度 >= 200

DEBUGPRINTFORML Setting Diary 7

DIARY:パルスィ:7 = 3

CALL CHARA_DIARY_PAGESETTING(パルスィ, 7)

ENDIF

Parsee befriends the player (Req
500+ Favorability)

IF DIARY:パルスィ:8 == 0 && CFLAG:パルスィ:好感度 >= 500

DIARY:パルスィ:8 = 3

CALL CHARA_DIARY_PAGESETTING(パルスィ, 8)

ENDIF

Parsee is jealous of the player (Req
1000+ Favorability)

IF DIARY:パルスィ:9 == 0 && CFLAG:パルスィ:好感度 >= 1000

DIARY:パルスィ:9 = 3

CALL CHARA_DIARY_PAGESETTING(パルスィ, 9)

ENDIF

Parsee has a crush on the player (Req
Parsee has Yearning)

IF DIARY:パルスィ:10 == 0 && TALENT:思慕

DIARY:パルスィ:10 = 3

CALL CHARA_DIARY_PAGESETTING(パルスィ, 10)

ENDIF

DEBUGPRINTFORML Outside Diary 11

Parsee can't drive the player away (Req
2000+ Favorability)

IF DIARY:パルスィ:11 == 0 && CFLAG:パルスィ:好感度 >= 2000

DEBUGPRINTFORML Setting Diary 11

DIARY:パルスィ:11 = 3

CALL CHARA_DIARY_PAGESETTING(パルスィ, 11)

ENDIF

Parsee STILL can't drive the player away (Req
2500+ Favorability)

IF DIARY:パルスィ:12 == 0 && DIARY:パルスィ:11 == 1 && CFLAG:パルスィ:好感度 >= 2500

DIARY:パルスィ:12 = 3

CALL CHARA_DIARY_PAGESETTING(パルスィ, 12)

ENDIF

Player saw Parsee crying in the tavern

IF DIARY:パルスィ:13 == 0 && CFLAG:パルスィ:1010 > 0

DIARY:パルスィ:13 = 3

CALL CHARA_DIARY_PAGESETTING(パルスィ, 13)

ENDIF

Parsee lost her virginity to the player

IF DIARY:パルスィ:14 == 0 && K60EN_PARSEE_STARTING_VIRGINITY && !K60_PARSEE_THINKS_IS_VIRGIN()

DIARY:パルスィ:14 = 3

CALL CHARA_DIARY_PAGESETTING(パルスィ, 14)

ENDIF