Scripting
The scripting language used by SWC is currently available for speeches of Custom NPCs and for interactions with items (e.g. egg incubator).
The new language (SWC Lisp) is a big step ahead from the old system. Here we want to list the major differences with the old system to ease the conversion from the old system to the new one.
Wildcards (OLD SWC Script Syntax)
SWC Lisp | Old Wildcard | Description | Example | Default | For Custom NPCs? |
---|---|---|---|---|---|
(get-name self) | %npc.name% | NPC's name | Joe Bloggs | N/A | Yes |
(get-race self) | %npc.race% | NPC's race | Nautolan | N/A | Yes |
(get-infofield self) | %npc.infofield% | NPC's infofield | Master Carpenter | N/A | Yes |
(get-gender self) | %npc.gender% | NPC's gender | Male | N/A | Yes |
(get-formal self) | %npc.formal% | NPC's formal greeting | Sir/Ma'am | N/A | Yes |
(is-ally? self) | %npc.ally% | is NPC IFF friendly? | N/A | N/A | Yes |
(is-enemy? self) | %npc.enemy% | is NPC IFF enemy? | N/A | N/A | Yes |
(is-neutral? self) | %npc.neutral% | is NPC IFF neutral? | N/A | N/A | Yes |
(is-unharmed? self) | %npc.unharmed% | is NPC unharmed? - requires (load "swclib") | N/A | N/A | Yes |
(is-slightly-wounded? self) | %npc.slightlywounded% | is NPC slightly wounded?- requires (load "swclib") | N/A | N/A | Yes |
(is-wounded? self) | %npc.wounded% | is NPC wounded?- requires (load "swclib") | N/A | N/A | Yes |
(is-badly-wounded? self) | %npc.badlywounded% | is NPC badly wounded?- requires (load "swclib") | N/A | N/A | Yes |
(get-name character) | %character.name% | Character's handle | Selatos | N/A | Yes |
(get-race character) | %character.race% | Character's race | Human | N/A | Yes |
(get-infofield character) | %character.infofield% | Character's 1st infofield | Emperor | Empty String | Yes |
(get-infofield2 character) | %character.infofield2% | Character's 2nd infofield | 1st Recon Division | Empty String | Yes |
(get-infofield3 character) | %character.infofield3% | Character's 3rd infofield | 2nd Expansionary Fleet | Empty String | Yes |
(get-gender character) | %character.gender% | Character's gender | Male | N/A | Yes |
(is-unharmed? character) | %character.unharmed% | is Character unharmed? - requires (load "swclib") | N/A | N/A | Yes |
(is-slightly-wounded? character) | %character.slightlywounded% | is Character slightly wounded? - requires (load "swclib") | N/A | N/A | ]Yes |
(is-wounded? character) | %character.wounded% | is Character wounded? - requires (load "swclib") | N/A | N/A | Yes |
(is-badly-wounded? character) | %character.badlywounded% | is Character badly wounded?- requires (load "swclib") | N/A | N/A | Yes |
(get-formal character) | %character.formal% | Character's formal greeting | Sir/Ma'am | N/A | Yes |
(get-entity-faction character) | %character.faction% | Character's current faction | New Republic | Freelance | Yes |
(is-owner? character) | %character.isowner% | Is character the owner of the NPC | Produces no output | Empty String | Yes |
(is-manager? character) | %character.ismanager% | Is character the manager of the NPC | Produces no output | Empty String | Yes |
(is-pilot? character) | %character.issupervisor% | Is character the owner of the NPC | Produces no output | Empty String | Yes |
(get-name (get-entity-faction character)) | %faction.name% | Character's faction's name | New Republic | Empty string (if freelance) | Yes |
(is-freelancer? character) | n.a. | is the character a freelancer? | Yes | ||
(faction-type (get-entity-faction character)) | %faction.type% | Character's faction's type | Mining | Empty string (if freelance) | Yes |
(faction-leader (get-entity-faction character)) | %faction.leader% | Character's faction's leaders name | Ellias | Empty String (if freelance) | Yes |
(faction-website (get-entity-faction character)) | %faction.website% | Character's faction's leaders name | http://swcombine.com (Link) | Empty string (if freelance) | Yes |
%owner.name% | Name of the NPC's owner | Darkness | Empty string if special owner (Market, None) | Yes | |
%owner.entityType% | Type of the NPC's owner | Faction or Character | Empty string if special owner (Market, None) | Yes | |
%owner.infofield% | Owner's 1st infofield | Emperor | Empty String | Yes | |
%owner.infofield2% | Owner's 2nd infofield | 1st Recon Division | Empty String | Yes | |
%owner.infofield3% | Owner's 3rd infofield | 2nd Expansionary Fleet | Empty String | Yes | |
(city-name character) | %location.city% | Current city name | City 327 | Unknown | Yes* |
(planet-name character) | %location.planet% | Current planet name | Glee Anselm | Unknown | Yes* |
(system-name character) | %location.system% | Current system name | Danju | Unknown | Yes* |
(sector-name character) | %location.sector% | Current sector name | Tapani | Unknown | Yes* |
(get-destination entity) | %location.destination% | Destination name | "Corellia sector" (if deep space) "Corellia system" (if heading to that system) "Corellia planet" (if heading in sublight) | ||
(get-eta entity) | %location.eta% | ETA for current travel | 3 days, 24 hours and 5 minutes | Unknown | Yes* |
(is-traveling? character) | n.a. | Checks if the character is traveling or not | Yes | ||
(get-name (get-container self)) | %container.name% | Current container name, e.g. the ship or vehicle standing in | Tydirium | Unknown | Yes |
(get-entity-type-name (get-container self)) | %container.type% | Current container type, e.g. the ship or vehicle standing in | Lambda Shuttle | Unknown | Yes |
(get-type entity-object) | %container.entityType% | Current container entity type, e.g. the ship, vehicle, city, planet, station | Ship, Vehicle, City, Planet, Space Station | N/A | Yes |
(in-room? entity-object) | n.a. | Checks if the entity is in any room at all, as opposed to outside on the surface | Yes | ||
cgt-year | %cgt.year% | Gets current CGT year | 12 | N/A | Yes |
cgt-day | %cgt.day% | Gets current CGT day | 183 | N/A | Yes |
cgt-hour | n.a. | Gets current CGT hour | 23 | N/A | Yes |
cgt-minute | n.a. | Gets current CGT minutes | 59 | N/A | Yes |
cgt-second | n.a. | Gets current CGT seconds | 59 | N/A | Yes |
timeofday | %time.ofday% | Gets current phase of day | Morning, Afternoon, Evening | N/A | Yes |
Entries with a "Yes" are available for custom NPCs. Entries with a "Yes*" may have some limitations on their use (e.g. they may not be available when the NPC cannot reliably determine the information without godmodding - for example location whilst in hyperspace).
Custom NPC Environment
This is the latest posting of functions and constants available to Custom NPCs. Some of these may not be synced to Main yet. Some are also listed above in Wildcards. Where possible, the syntax, required&optional parameters and example usage & evaluation are included.
SWC Lisp | Required &Optional ("&") Parameters | Description | Example Evaluation | Default eval | Testing Status |
---|---|---|---|---|---|
self | The object running the script (NPC, item...). | Test Tickle | n/a | ||
character | The character interacting with the object running the script. | Kay Dallben | n/a | ||
evar | 'name defaultValue | This is a persistent variable in the context of self. See Persistent Variables for usage notes. | special case | defaultValue | |
ovar | 'name defaultValue | This is a persistent variable in the context of self & character. See Persistent Variables for usage notes. | special case | defaultValue | |
svar | 'name defaultValue | This is a persistent variable in the context of the current *session*. Session is the interaction between a PC and a scripted entity. See Persistent Variables for usage notes. | special case | defaultValue | |
#t | This is "True" | #t | #t | ||
+ | a b &d &e … | Basic addition function. Takes at least 2 numbers. | a+b | n/a | |
- | a b &d &e … | Basic subtraction function. Takes at least 2 numbers. Evaluates as a - b - c - d … or a - (sum b…n) | a-b-c-d… | n/a | |
> | a b | Preposition. Answers: Is a Greater than b? | #t | n/a | |
* | a b | Basic multiplication function. Takes at least 2 parameters. | a*b | n/a | |
/ | a b | Basic division function. Takes at least 2 parameters. | a/b | n/a | |
ge? | a b | Preposition. Answers: Is a Greater than OR equal to b? | #t | n/a | |
>= | a b | Preposition. Answers: Is a Greater than OR equal to b? | #t | n/a | |
le? | a b | Preposition. Answers: Is a less than OR equal to b? | #t | n/a | |
<= | a b | Preposition. Answers: Is a less than OR equal to b? | #t | n/a | |
gt? | a b | Preposition. Answers: Is a Greater than b? | #t | n/a | |
lt? | a b | Preposition. Answers: Is a less than b? | #t | n/a | |
< | a b | Preposition. Answers: Is a less than b? | #t | n/a | |
and | a b &c… | Logical Operand. #t if all its parameters are #t | #t | n/a | |
or | a b &c… | Logical Operand. #t if any of its parameters are #t. If it finds a #t, it will stop evaluating the rest of the parameters. | #t | n/a | |
not | a | Logical Operand. #t if a is #f | #t | n/a | |
concat | stringA &stringB | a concatenated string made up of the provided strings. | abc… | n/a | |
strlen | string | number of characters in the provided string a | 4 | n/a | |
trim | string &character_mask | removes:"\0" null "\t" tab "\n" new line "\x0B" vertical tabs "\r" carriage returns and " " spaces. &character_mask can be used to trim only some of those. | sample string | n/a | |
substr | string start &length | a string made of of the sequential characters within the provided string, beginning at the start character, and ending at &length, if provided. If &length is not provided, the rest of the string is provided. | ample string | n/a | |
stripos | stringA searchFor &offset | the start position of searchFor if contained in stringA, beginning the search at &offset. | (stripos "sample string" "mp") -> 2 | n/a | |
length | listA | number of elements in listA | (length (list 'a 'b 'c 'd 4)) -> 5 | n/a | |
reverse | listA | a list of the reversed elements of listA | (reverse (list 'a 'b 'c)) -> (c b a) | n/a | |
sublist | listA offset &length &preserve_keys | a list of the elements of listA beginning at offset and continuing to the end of listA OR to &length elements if provided. &preserve_keys should be #t or nil. NOTE: sublist will (perhaps unexpectedly) return strings from a list of symbols. Be aware when using it to get a sublist involving symbols. This is important because (eq? 'a "a") -> #f | (sublist (list "a" 'b "c") 0 2) -> `("a" "b") | n/a | |
sort | listA | a list of sorted elements of listA. Sort is alphanumeric. | (sort `(b c a)) -> (a b c) | n/a | |
nth-of | listA n | the element of listA at position n. 0 is the first element NOTE: nth-of will (perhaps unexpectedly) return strings from a list of symbols. Be aware when using it to get nth-of from a list involving symbols. This is important because (eq? 'a "a") -> #f | (nth-of `(a b c) 1) -> "b" | n/a | |
rand | &min &max | random number between &min &max. If not provided &min is 0 and &max is ?. See Randomization topic. | (rand 0 5) -> 2 | n/a | |
rand-from-list | listA | random element from listA NOTE: Be aware that rand-from-list will not return any Symbol if you give it a list of symbols. It will return a STRING if the random element it finds is a symbol. This is important because (eq? 'a "a") -> #f | (rand-from-list `(a b c)) -> "b" or "a" or "c" | n/a | |
get-entity-type-id | name | Type ID for the entity type name. {Ship, Vehicle, City, Planet, Space Station} | (get-entity-type-id 'Planet) -> | n/a | |
get-type-type | typeID entityType | returns a full TYPE | (get-type-type 298 (enum "EntityType" "ITEM")) is equal to (get-item-type 298) | ||
get-creature-type | typeID | returns the type of Creature | (get-creature-type 175) returns the type for an Eye-Snatcher | ||
get-droid-type | typeID | returns the type of Droid | (get-droid-type 14) gets the droid type obj for Pit Droids | ||
get-item-type | typeID | returns the type of Item | (get-item-type 298) returns the type of a Focusing Crystal | ||
get-npc-type | typeID | returns the type of NPC | (get-npc-type NUM) returns the type for a NPC of typeid NUM | needs testing | |
get-type-of | entity | returns the type object for the entity | (get-type-of self) could return the type for a Quest NPC (if self is a quest npc) | ||
get-npc-owner | returns the "NPC Owner" object | useful for an is-unclaimed? check. | |||
get-hostile-owner | returns the "Hostile Owner" object | ie checks if it is a spawned Bandit/Creature | |||
get-market-owner | returns the "Market Owner" object | ||||
get-character | name | entity-object for character "name" | (get-character "Kay Dallben") | n/a | |
get-faction | name | faction-object for faction "name" | (get-faction "Darkness") | n/a | |
get-npc | id | npc-object for NPC with ID id | (get-npc 155408) | n/a | |
get-quest | id | quest-object for quest with ID id | (get-quest 4408) | n/a | |
get-item | id | item-object for item with ID id | (get-item 481099) | n/a | |
get-ship | id | ship-object for ship with ID id | (get-ship 448088) | n/a | |
get-vehicle | id | vehicle-object for vehicle with ID id | (get-vehicle 46846816) | n/a | |
get-room | id | room object for room ID. Rooms are commonly numbered among ALL of a given entity type. So all VSDs have the same room numbers, and no other entity has those room numbers. | (get-room 4478) | n/a | |
get-id | entity | ID for the entity | (get-id (get-npc 100)) -> 100 | n/a | |
get-name | entity | name of the object | (get-name (get-vehicle 1150488)) | n/a | |
get-formal | entity | Sir if gender is male, Maam if gender is female. | (get-formal (get-character "Kay Dallben")) -> Sir | n/a | |
get-infofield | entity | string of the first infofield of entity | (get-infofield (get-npc 111548)) | empty string | |
get-infofield2 | pc-entity | string of the 2nd infofield of entity | (get-infofield2 (get-character "Kay Dallben")) | ||
get-infofield3 | pc-entity | string of the 3rd infofield of entity | (get-infofield3 (get-character "Kay Dallben")) | ||
get-race | entity | string representing race of the entity | (get-race self) | n/a | |
get-gender | entity | string of the gender of entity | (get-gender self) ->Male | n/a | |
get-hp-status-text | entity | string of the hp-status-text {unharmed, slightly-wounded, etc.} | (get-hp-status-text self) | n/a | |
is-ally? | test &source | Preposition. Answers: is test an ally to &source (default: self) | (is-ally? (get-npc 445158)) | n/a | |
is-neutral? | test &source | Preposition. Answers: is test neutral to &source (default: self) | (is-neutral? (get-npc 4408)) | n/a | |
is-enemy? | test &source | Preposition. Answers is test an enemy to &source (default: self) | (is-enemy? (get-npc 4408)) | n/a | |
is-freelancer? | test-character | Preposition. Answers: is test-character a freelancer? | (is-freelancer (get-character "Kay Dallben")) -> nil | n/a | |
faction-owned? | entity | Preposition. Answers: is the entity owned by a faction? | (faction-owned? self) | n/a | |
get-entity-faction | entity | faction-object for the faction entity belongs to? | n/a | needs testing | |
faction-type | faction-entity | type of faction | String? | needs testing | |
faction-leader | faction-entity | leader of faction | String? | needs testing | |
faction-website | faction-entity | website of faction | String? | needs testing | |
get-owner | entity | owner object of entity | (get-owner self)-> Kay Dallben | ||
get-type | entity | type of entity | type ID or string? | needs testing | |
get-entity-type-name | entity | name of type of entity | string? | needs testing | |
is-owner? | Preposition. Answers: is character the owner of self | (is-owner?) -> #t | n/a | ||
is-commander? | Preposition. Answers: is character the commander of self | (is-commander?) | |||
is-manager? | Preposition. Answers: is character the manager of self | (is-manager?) | |||
is-pilot? | Preposition. Answers: is character the pilot of self | (is-pilot?) | |||
is-supervisor? | Preposition. Answers: is character the supervisor of self | (is-supervisor?) | |||
in-room? | entity | Preposition. Answers: is entity in the same room as self? | (in-room? (get-NPC 4808)) | n/a | |
is-traveling? | entity | Preposition. Answers: is entity travelling? | (is-traveling? (get-ship 3334)) | n/a | |
get-container | entity | entity-object for container of entity. | (get-container self) | n/a | |
get-destination | entity | destination of entity | needs testing | ||
get-eta | entity | eta of arrival of entity to its destination | needs testing | ||
get-location | entity | String of location (currently including hyperlinks) if viewable without godmoding. | needs testing | ||
city-name | entity | Name of the city containing entity? | needs testing | ||
planet-name | entity | name of the planet containing entity? | needs testing | ||
system-name | entity | name of the system containing entity? | needs testing | ||
sector-name | entity | name of the sector containing entity? | needs testing | ||
send-message | sender receiver message &subject | Output: Sends a DM to receiver, from sender with message and subject &subject. Receiver and Sender must be any PC-object and self | needs testing | ||
flash | type{'green 'red 'blue 'good 'bad 'info} message | Puts a small coloured bar with the message on the screen of character. | (flash 'green "You did it!") | n/a | |
null | null | null | |||
empty | Use for the empty list `() | null | |||
nil | aka #f | null | |||
cgt-year | current year | ||||
cgt-day | current day | ||||
cgt-hour | current hour | ||||
cgt-minute | current minute | ||||
timeofday | string of timeofday Morning Afternoon Evening Night | n/a | |||
teleport-to-room | entities container room | ? | needs testing | ||
leave-room | character direction | ? | needs testing | ||
say | message &close | Output: NPC "says" message. &close is boolean. If true, this will start a new paragraph. | |||
describe | message &close | Output: NPC "describes" message. &close is boolean. If true, this will start a new paragraph. | |||
ooc | message &close | Output: NPC "oocs" message. &close is boolean. If true, this will start a new paragraph. | |||
say-c | message | Output: NPC "says" message, continuing previous paragraph and using that formatting | |||
describe-c | message | Output: NPC "describes" message, continuing previous paragraph and using that formatting | |||
ooc-c | message | Output: NPC "oocs" message, continuing previous paragraph and using that formatting | |||
add-response | message callback | Input: Adds a clickable option labelled 'message' that will a) display "You say " message; and b) run the callback function. NOTE: Currently the callback functions may not have any parameters. | |||
add-action | message callback | Input: Adds a clickable option labelled 'message' that will a) display "You " message; and b) run the callback function. NOTE: Currently the callback functions may not have any parameters. | |||
add-text | message callback | Input: Adds a clickable option labelled 'message' that will not display anything and simply run the callback function. NOTE: Currently the callback functions may not have any parameters. | |||
add-input | not implemented | Input: creates a text box for the user to type something in. In progress. |
Conditional Statements
The biggest differences are:
- the "=" is no longer used to do comparisons;
Old system:
!if character.race=Gungan! Don't slip over! !if character.race=Human! Humans are the best! !ifnot character.race=Human! Alien scum!
New system:
(cond [(eq? (get-race character) "Gungan") (say "Don't slip over!") (say "Alien scum!")] [(eq? (get-race character) "Human") (say "Humans are the best!")] [#t (say "Alien scum!")])
OR
(cond[(eq? (get-race character) "Gungan") (say "Don't slip over!") (say "Alien scum!")]) (cond [(is-owner?) (say "Oh, uh. Welcome Boss!")]
- with cond statement, the conditions are tested sequentially until one of them is true, and then it evaluates it and stops testing. This is much like an If...ElseIf...ElseIf. This means that if you have two statements, you must put them inside the same condition. If you have multiple alternate conditions (ElseIfs) to test, you must ensure that at least one of them evaluates true every time. Commonly this is done with a final [#t] condition.
- You can use cond statements as a simple IF by only including one test.
Old system:
Responses: !if character.race=Baragwin! !if character.gender=Female! Excuse me, how do you know I am a female? -> Baragwin female !if character.race=Baragwin! !if character.gender=Male! Excuse me, how do you know I am a male? -> Baragwin male !ifnot character.race=Baragwin! I'd like to have more information on the museum. -> info !ifnot character.race=Baragwin! What can I do here? -> what to do !ifnot character.race=Baragwin! Do I need to pay an entrance fee? -> fee
New system: NOTE: Technically, the last ElseIf can just be #t rather than (not (eq? (get-race character) "Baragwin")). This is because the first two checks cover all cases where the character could be a Baragwin (female or male).
(cond [(and (eq? (get-race character) "Baragwin") (eq? (get-gender character) "Female")) (add-response "Excuse me, how do you know I am a female?" Baragwin-female)] [(and (eq? (get-race character) "Baragwin") (eq? (get-gender character) "Male")) (add-response "Excuse me, how do you know I am a male?" Baragwin-male)] [(not (eq? (get-race character) "Baragwin")) (add-response "I'd like to have more information on the museum." info) (add-response "What can I do here?" what-to-do) (add-response "Do I need to pay an entrance fee?" fee)][#t])
Note 2: Also, since the two add-responses in the first cases are so similar, you can combine them and toss the M/F determination, if important, into the Baragwin defun next conversation step.
(cond [(eq? (get-race character) "Baragwin") (add-response (concat "Excuse me, how do you know I am a " (get-gender character) "?") Baragwin-female)] [#t (add-response "I'd like to have more information on the museum." info) (add-response "What can I do here?" what-to-do) (add-response "Do I need to pay an entrance fee?" fee)])
Variable Examples
The following little script shows how to use session variables.
(defvar hp-session-var (svar 'hp 10)) (defvar str-session-var (svar 'str 5)) (defvar rand-val (svar 'rand (rand 1 5))) (defvar setted-rand-val (svar 'setted-rand-val (rand 11 15)))
(defun (incr-hp val) (set-var! hp-session-var (+ hp-session-var val)))
(defun (incr-str val) (set-var! str-session-var (+ str-session-var val)))
(defun start (ooc (concat "Your HP is: " hp-session-var ". Your Str is: " str-session-var ". The rand-val is: " rand-val ". The 'setted-rand-val' is: " setted-rand-val "." ) ) (add-action "Set the setted-rand-val to store the rand between 6 and 10 for the whole session." set-rand-val) (add-action "Add 2 HP" add-2hp) (add-action "Sub 4 HP" sub-4hp) (add-action "Add Str to HP" add-str-to-hp) (add-action "Add Rand 1 - 9 to Str" add-rand-to-str))
(defun add-2hp (incr-hp 2) (start))
(defun sub-4hp (incr-hp -4) (start))
(defun add-str-to-hp (incr-hp str-session-var) (start))
(defun set-rand-val (set-var! setted-rand-val (rand 6 10)) (start))
(defun add-rand-to-str (incr-str (rand 1 9)) (start))
Public Script Modules
See the Rules Page on SWC for additional explanation.
swclib
(load "swclib")
is-unharmed? player-NPC-object - returns #t if player-NPC-object's HP-Status-Text is "unharmed" EG: (is-unharmed? character) -> #t
is-slightly-wounded? player-NPC-object - returns #t if player-NPC-object's HP-Status-Text is "slightly wounded"
is-wounded? player-NPC-object - returns #t if player-NPC-object's HP-Status-Text is "wounded"
is-badly-wounded? player-NPC-object - returns #t if player-NPC-object's HP-Status-Text is "badly wounded"
Contact: Selatos; Kay Dallben
funlib
(load "funlib")
join separatorCharacter list - Combine the elements of list with the separatorCharacter to form a string EG: (join ", " (list "Green" "Blue" "Yellow")) -> "Green, Blue, Yellow,"
map function list - Call function for each member of list and return the list of results. E.g. (map (lambda (x) (+ x 2)) (list 1 0 4) ) -> (3 2 7)
apply-foreach function list - Call function for each member of list but do not return results. e.g. (apply-foreach (lamda (x) (say x)) (list "I like" "cheesy poofs." "Do you?")) -> I like cheesy poofs. Do you?
append list element - adds element to the end of list e.g. (append (list 1 2) 3) -> (1 2 3)
reduce function init list - reduce a list to a single value, using the combiner function provided, which function takes two inputs init and (car list) e.g. (reduce (lamda (x y) (+ x (* 2 y))) 0 (list 1 2 3)) -> (((0 + 2*1) + (2*2)) + (2*3)) -> 12
repeat-fn function NumTimes object - repeat function Numtimes on object e.g. (repeat (lamda (x) (+ x 1)) 4 0) -> 4
eq-lists? listA listB - preposition: is listA equal to listB -> are all elements of A = all elements of B. - Does NOT currently take into account lists of lists, so just 1D lists atm. e.g. (eq-lists? `(a b c) `(d e f)) -> #f (eq-lists? `(a b c) `(a b c)) -> #t (eq-lists? `(a b c) `( `(a) b c)) -> Error.
neq? atomA atomB - preposition: is atomA NOT equal to atomB e.g. (neq? 1 2) -> #t
KayD-StringShortcuts
(load "KayD-StringShortcuts")
General Descrip: For inserting appropriate pronoun string based on gender.
heshe player-NPC-object EG: (say (concat "Yes, " (heshe (get-npc 54486)) " is pretty silly.")) -> "Yes, he is pretty silly." EG: (describe (concat (HerHis self) " gun points directly at you.")) -> Her gun points directly at you.
HeShe player-NPC-object
herhis player-NPC-object
HerHis player-NPC-object
herhim player-NPC-object
HerHim player-NPC-object
Contact: Kay Dallben
Basic Custom NPC Interaction
Conversation
Syntax | Example of Use | Actual Output |
---|---|---|
say string | (say "Hello World!") | "Hello World!" |
describe string | (describe "The droid beeps and burps.") | The droid beeps and burps. |
ooc string | (ooc "Now go to the mentioned location and talk to the NPC there.") | |
add-response string next-function) | (add-response "Wow, I didn't know that!" explainmore) | say "Wow, I didn't know that!" |
add-action string next-function | (add-action " exit the room." room12) | You exit the room. |
LISP Language Functions
These are some general CLISP functions that are useable in SWC-LISP, and not necessarily included in the dbg-env tables above.
SWC Lisp | Required &Optional ("&") Parameters | Description | Example Evaluation | Default eval (if applicable) |
---|---|---|---|---|
car | list | The first element of the list. Aka 'First' | (car `(1 2 3)) -> 1 | n/a |
cdr | list | A list of all the elements of the list, in order, except the first. AKA 'Rest' | (cdr `(1 2 3)) -> (2 3) | n/a |
cons | expr1 expr2 | constructs a list from the two expressions provided. Typically used to prepend an element onto a list (push), using (cons atom1 list). Careful when consing atoms only. That creates a "dotted list" which can result in unexpected behaviour. If you want to make a list with just one element, either use (list atom) or `(atom), or (cons atom `()) aka (cons atom empty). | (cons 1 `(2 3)) -> (1 2 3) | n/a |
list | expr1 expr2 ... exprN | Constructs a list out of atoms or lists, or I guess symbols. | (list 1 2 `(3)) -> (1 2 (3)) | n/a |
empty? | list | checks if you have an empty list. Can have unexpected behaviour if attempting to store an empty list in a persistent variable. | (empty? `()) -> #t (empty? `(1)) -> #f | n/a |
eq? | atom1 atom2 | Preposition: Are the two provided atoms equal? Unsure exactly which "eq" from LISP documentation this really is. Does not work for Lists. | (eq? 1 1) -> #t (eq? 1 2) -> #f ... | n/a |
nth-of | list index# | aka "nth". Returns the nth element of list. Note: 0 is the first element. | (nth-of `(1 2 3) 0) -> 1;
(nth-of `(1 2 (3 4)) 2 -> (3 4) |
n/a |
floor | ||||
ceil | ||||
round | ||||
log | ||||
modulo | ||||
stochastic_round |
Admin-Only Functions
- is-force-aware?
- get-skill
- get-force-skill
Admin scripts now have xvars and yvars which allow arbitrary context pairs (superseding q, o, t, e, etc. vars).
User scripts still have s-, o-, and e- vars
- *vars can now properly handle lists of values in addition to scalar values. Storing an instance of a class is not supported and (should) result in an exception being thrown.
How to Pass Parameters in Functions
Below you can see a simple example of creating a function accepting two parameters, and passing them.
(defun (myfun a b) (ooc (concat "I do something with " a ", then I do something with " b)))
(defun start (myfun "turkey" "salami"))
Another example with numbers. This calculate the absolute of a number.
(defun (abs x) (cond [(lt? x 0) (* x -1)] [#t x]))
(defun start (say (concat "The absolute of 20 + -44 is " (abs (+ 20 -44)))))
Debugging Functions
- dbg-break added to trigger an exception (ignoring the rest of the script) and print supplied values, for example (dbg-break self character (+ 1 2)) will display info about the current entity, current character, and the number 3
- note that if you put (dbg-break) in the global scope (a line on its own), it'll block the whole script at startup. Instead, you must use it inside another function, in the point where you want the script to stop.
- dbg-pp added to print values for debugging without triggering an exception (script continues), using the same semantics as dbg-break
- dbg-env added, which dumps the entire symbol table (very large) and can be used to get basic information about the API to help with missing documentation
Understanding Errors
Most often, if you get an error it is a problem of parenthesis. When you save the script, the parser checks only for matching parenthesis; however, if the total of open parenthesis matches the total of closed parenthesis, the parser reports no errors on saving.
Symbol [name] is not defined!
If you get this error while the script runs, it could mean that there are misplaced parenthesis. In this case, go through your script placing your cursor on the end parenthesis to see if everything is ok.
If the error is not due to misplaced parenthesis, check that the name is not mispelt. If ok, check that the call to the function comes before the function called.
Symbol -> is not defined!
It is the easiest to fix. You've just written a "->" in an add-response function, between the end of text and the name of the function to go to. The old system used that symbol, but the new system need not that. Just remove that "->".
A second case is if you've added a parameter to the describe function different from close. Example, the old 'left alignment keyword, now invalid.
Symbol is undefined and cannot be evaluated
You've probably forgotten to specify where to go after an add-response text. Simply add the name of the function to continue with.
Mind the parenthesis if you have a concat function in add-response or other function with parameters. Example, this code is right:
(defun start (say "Hello, how may I help you?") (cond [(eq? (get-race character) "Kuati") (add-response "Excuse me, your dress is very elegant. May I know what caste are you?" caste01)] [(not (eq? (get-race character) "Kuati")) (add-response (concat "I see you are a " (get-infofield self) ". What do you do, exactly?") do01) (add-response "Are you a real expert on ships?" expert01) (add-response "Very kind of you, but I am just browsing. No need for help." end01)]))
but if you write the add-response with the concat function as
(add-response (concat "I see you are a " (get-infofield self) ". What do you do, exactly?" do01))
you get this type of error, because the closing parenthesis of the concat function must go after the string end and before the next-function-name parameter.
Symbol set-var is undefined and cannot be evaluated
The correct syntax is set-var! (with the 'bang') and not set-var or setvar. Check your syntax.
Invalid speech option selected
This is a generic error, meaning that any thing wrong in the next-function-name called by the user click may cause this error. A syntax error, a logic error... Below you find some examples. Note that this error appears when you try to click on an answer, therefore you should look for the function called by that answer. You can use the (dbg-xx) functions in the functions called by the add-action/add-response/add-text to check your code for unexpected evaluation results.
- If you're trying to concatenate a text with a describe, you'll get this error. Example:
(say (concat "Well, another protocol droid you can see here is the SP-4. It is defined as an analysis droid and it uses the same chassis and many parts assembled in the cheaper PK-series worker droid. You cannot say that it is made to resemble its owner..." (describe "winks")))
The solution is to put the describe in a single line, all alone, and remove the concat in the say function. `concat` only assembles several strings into one string. `describe` is a function that does not evaluate to a single string, and so concat cannot make proper use of it.
- A conditional statement with a wrong use of keywords:
(eq? (get-entity-faction character) "Galactic Empire")
is bugged;
(eq? (get-name (get-entity-faction character)) "Galactic Empire")
is correct.
- Adding a missing [#t] to a conditional statement.
`set-var!` can only be called on *vars
wip
Other Resources
You can also check out: http://racket-lang.org/ which is a version of LISP similar to SWC-Lisp and decent to practice with to get the basic idea of programming in LISP.
There is also LISP In Small Parts which is a good simple overview and basic introduction to LISP's methodology of programming. It primarily focuses on thinking about how to use the language, rather than memorizing the CLISP native functions (which won't help you in SWC-LISP).