DinkC Reference
website·Indexed 31 days ago
https://dinkcreference.netlify.app/A comprehensive reference for DinkC scripting functions used in Dink, Freedink, DinkHD, and YeDink. Includes documentation for sprite manipulation (sp_x, sp_y, sp_seq), dialogue systems (say_xy, say_stop_npc), and game state controls.
What's inside DinkC
- DinkC is the scripting language used to create D-Mods and add-ons for Dink Smallwood. It is designed to be accessible to those with experience in scripted or compiled languages like BASIC or Pascal, and does not require knowledge of C. The language is highly versatile, allowing for a wide range of custom behaviors within the game engine.
Overview of the DinkC scripting language
DinkC is a procedural scripting language used to power game-related logic in Dink Smallwood, including conversations, cutscenes, and enemy behavior. Its syntax superficially resembles C/C++. Key features include:
- Support for procedural structure.
- Local and global dynamic variable creation with custom names (global variables are automatically saved with the player data file).
- The ability to attach scripts to objects, persons, monsters, or screens.
Create a Caster enemy
Casters are enemies that randomly cast spells or perform actions. This is typically implemented usingset_callback_random()to trigger a custom function at random intervals. For advanced casters (like dragons), settingsp_brain()to 10 causes the enemy to call its attack procedures randomly based onsp_attack_wait(), regardless of whether a target is in range.// magicpil.c void main(void) { sp_base_walk(¤t_sprite, 130); sp_speed(¤t_sprite, 1); sp_brain(¤t_sprite, 9); sp_touch_damage(¤t_sprite, 4); sp_hitpoints(¤t_sprite, 10); sp_exp(¤t_sprite, 5); sp_target(¤t_sprite, 1); // Call "harm" function randomly every 1 to 3 seconds set_callback_random("harm", 1000, 2000); } void harm(void) { say("`%<Casts Harm>", ¤t_sprite); hurt(1, 2); }Make a sprite follow another sprite using sp_follow
The
sp_follow(active_sprite, target_active_sprite)function causes theactive_spriteto move toward thetarget_active_spriteuntil it is within 40 pixels. The following constraints apply:- Brain Requirements: The function only affects sprites with a
sp_brain()value of 0, 3, 5, 7, 9, 10, or 16. - Speed Requirements: The sprite must have a
sp_speed()value greater than 0. - Movement: The sprite moves toward the target but cannot maneuver around obstacles.
- Diagonal Movement: By default, sprites move in cardinal directions (up, down, left, right). If
set_smooth_follow()is set to 1, the sprite will also use diagonal movement. - Version Note: In version 1.07,
set_smooth_follow()is unavailable, and sprites only move in cardinal directions.
int sp_follow(int active_sprite, int target_active_sprite);- Brain Requirements: The function only affects sprites with a
Call other scripts using external() and spawn()
Scripts can trigger the execution of other scripts using two different methods:
external(): Synchronous call. The caller script pauses and waits for the called script to finish before continuing.spawn(): Asynchronous call. Creates a new script instance that runs independently. Spawned scripts persist until they are explicitly terminated usingkill_this_task().
// Example of external() - Caller waits void main(void) { external("grocery", "main"); // This line runs only after grocery.c finishes } // Example of spawn() - Spawner continues immediately void main(void) { spawn("grocery"); // Spawner continues while grocery.c runs in parallel kill_this_task(); }Create loops using goto
Since DinkC lacks
whileorforloops, loops are created by placing a label before a block of code and usinggototo jump back to that label based on a condition.Warning: Infinite loops without a pause will freeze the game. To prevent this, include a
wait()statement within the loop to allow other game events and player input to process.void talk(void) { freeze(1); int &counter = 0; loop: say_stop("I'm going to say this 10 times!", 1); &counter += 1; if (&counter < 10) { goto loop; } // Example of a non-freezing infinite loop // loop_forever: // say("I won't freeze the game!", 1); // wait(100); // goto loop_forever; say_stop("Whew, glad I'm done with that!", 1); unfreeze(1); }Create and call custom procedures
Custom procedures allow you to organize code into reusable blocks. Unlike predefined procedures, they are not called by the engine and must be invoked manually. You can call a custom procedure within the same script or from an external script using theexternal()function.// Example 1: Calling a procedure in the same script void main(void) { say_banana(); } void say_banana(void) { say("Banana!", 1); } // Example 2: Calling a procedure in a different script // In banana2.c void main(void) { external("bananax", "say_banana"); } // In bananax.c void say_banana(void) { say("Banana!", 1); }Implement a plot system using global state variables
To create a plot or quest in a D-Mod, use a global integer variable to track the current state of the story. This allows characters to respond differently based on the player's progress. Initialize the variable inmain.cusingmake_global_intand update its value as the player completes specific goals.// excerpt from main.c void main(void) { // Initialize story state make_global_int("&story", 0); // 0 – Nothing happened // 1 – Person 1 asked Dink to tell Person 2 to shut up // 2 – Dink told Person 2 to shut up // 3 – Dink rewarded by Person 1 }Implement item and magic script lifecycles
Item and magic behavior is controlled via scripts. The engine calls specific procedures based on the item's state. To give a player an item, use
add_item()oradd_magic().Procedure Lifecycle:
pickup(): Called immediately afteradd_item()oradd_magic(). Use this for effects that trigger simply by possessing the item.arm(): Called when the player arms the item. Use this to modify player stats (e.g., increasing strength) or change attack animations.armmovie(): Called when the player manually arms the weapon (not called ifarm_weapon()is used). Use this for dialogue or visual cues.disarm(): Called when the item is disarmed. You must includekill_this_task()at the end of this procedure to ensure the script terminates.
Special Case: Loading Games When
load_game()is called, the engine runsdisarm()followed byarm()for the currently equipped weapon and magic.armmovie()is not executed during a game load.Perform jumps using goto and labels
DinkC supports jumping to different parts of a script using the
gotostatement. This is the primary way to implement complex logic (like OR conditions) since standard logical operators are not supported.To use a jump:
- Define a label in the script by writing a name followed by a colon (e.g.,
healthy:). - Use
goto labelname;to immediately move execution to that label.
void talk(void) { if (&life == &lifemax) { goto healthy; } if (&strength > 10) { goto healthy; } say_stop("I'm not feeling so good, Jack.", 1); goto done; healthy: say_stop("I'm healthy as a horse!", 1); done: say_stop("I will say this no matter what.", 1); }- Define a label in the script by writing a name followed by a colon (e.g.,
Display a BMP image over the screen background using copy_bmp_to_screen
The
copy_bmp_to_screen(string bmpfile)function copies a specified BMP image onto the screen, covering the background area (including the status bar and tiles). Sprites remain visible and function normally.Requirements and Constraints:
- Resolution: The BMP must be exactly 640px x 480px.
- Palette: The image should use the current palette unless the game is running in true-color mode. If a different palette is used in non-true-color mode, the game will switch to that palette (similar to
load_palette). - Removal: Calling
draw_backgroundwill remove the BMP and revert the screen to the original tiles.
Caveats:
- In the original Dink engine, loading a save file after a palette change via this function causes tiles to revert to the Dink palette, while sprites retain the new palette. Subsequent palette changes may not take effect.
void main(void) { // Copies "tester.bmp" from the tiles folder to the screen copy_bmp_to_screen("tiles/tester.bmp"); }Create a Toucher enemy
Touchers are basic enemies that harm the player only upon physical contact. They typically use asp_brain()value of 9 to ensure constant movement. Key configuration functions includesp_touch_damage()for contact damage,sp_hitpoints()for health, andsp_exp()for experience granted upon death.// pillbug.c void main(void) { sp_base_walk(¤t_sprite, 130); sp_speed(¤t_sprite, 1); sp_brain(¤t_sprite, 9); // Harm Dink for at most 4 hitpoints on touch sp_touch_damage(¤t_sprite, 4); // Die after 10 hitpoints of damage sp_hitpoints(¤t_sprite, 10); // Give Dink 5 experience points sp_exp(¤t_sprite, 5); } void die(void) { // Respawn in 5 minutes int &editor_sprite = sp_editor_num(¤t_sprite); if (&editor_sprite != 0) editor_type(&editor_sprite, 6); // Randomly create a small powerup using emake.c &save_x = sp_x(¤t_sprite, -1); &save_y = sp_y(¤t_sprite, -1); external("emake","small"); }