| Name | Typ | Von |
|---|---|---|
| Little Achievements | Definition | Einzelkämpfer |
Dieses Skript speichert Bedingungen in einer externen Datei und lädt sie wieder. So lässt sich ein einfaches lokales Achievement-System bauen, dessen Zustände unabhängig von einem bestimmten Spielstand erhalten bleiben.
Achievements gelten nur auf dem Gerät, auf dem sie erreicht wurden, und lassen sich nicht übertragen (zumindest habe ich versucht, Schummeln für normale Nutzer schwer genug zu machen). Veröffentlichst du dein Spiel auf einer Plattform wie Steam oder GOG, nutze besser deren ausgereifte Achievement-Systeme.
Anleitung
- Füge das Hauptskript im Skripteditor von Visionaire Studio hinzu und lege es als Definitionsskript fest.
- Lege im Editor Bedingungen für die Achievements mit dem Anfangswert false an (keine kombinierten Bedingungen). Ihre Namen müssen im ganzen Projekt eindeutig sein.
- Trage die Namen dieser Bedingungen in die Tabelle
achvm_conditionsdes Skripts ein. - Ändere den geheimen Schlüssel.
- Rufe "save_achievements()" auf, sobald sich im Spiel eine der Achievement-Bedingungen ändert.
- Rufe "load_achievements()" nach dem Laden eines Spielstands auf. Füge dazu auch das GameLoaded-Skript als Definitionsskript hinzu.
Du musst dafür kein eigenes Definitionsskript anlegen, du kannst den Code auch ins Hauptskript schreiben. Vielleicht willst du den Event-Handler "engineEvent" aber auch für andere Funktionen nutzen, deshalb habe ich ihn getrennt gehalten. Hast du diesen Event-Handler in deinem Projekt schon, ergänze dort einfach die Funktion "load_achievements()".
Willst du die Achievements statt in einer eigenen Datei in der config.ini speichern, aktiviere den INI-Modus. Das Lesen und Schreiben der config.ini musst du dann allerdings mit einem eigenen Skript erledigen.
- Rufe "get_achievements()" in deinem config.ini-Skript auf und schreibe den zurückgegebenen String in die INI-Datei. Schreibe die config.ini jedes Mal neu, wenn sich eine Achievement-Bedingung ändert.
- Übergib den aus der config.ini gelesenen Achievement-String an die Funktion "set_achievements()". Lies die config.ini beim Spielstart und nach dem Laden eines Spielstands.
Hauptskript
--[[
Little Achievements
-------------------
Script for saving and loading condition states to/from an external file. It allows implementation of a basic local achievement system where condition states are available independent from a particular game session. Achievements are only valid on the device they were obtained and cannot be shared (at least I tried to make cheating difficult enough for the ordinary user). If you release your game on a proper game platform like Steam or GOG, you better make use of their advanced achievement systems. Enable the INI mode, if you want to save the achievements in the config.ini file instead of in a separate file. You would have to handle config.ini writing and reading through your own script though.
Author: Einzelkämpfer
Version: 1.2
Date: 2023-05-21
Requirements: Visionaire Studio 5.2 or higher
License: MIT License (details at the bottom of the script)
How to use (A: Regular mode / B: INI mode):
1. Add your achievement conditions to the "achvm_conditions" table below and change the "secret_key".
A2. Call "save_achievements()" whenever you change one of the achievement conditions in your game.
A3. Call "load_achievements()" after loading a savegame (see the "GameLoaded" script).
B2. Call "get_achievements()" from your config.ini script and write the string you get to the .ini file.
Rewrite the config.ini whenever you change one of the achievement conditions in your game.
B3. Pass the achievement string read from the config.ini to the "set_achievements()" function.
Read the config.ini at game start and after loading a savegame.
ATTENTION: THIS VERSION OF THE SCRIPT HAS ONLY BEEN TESTED ON A SINGLE WINDOWS 10 MACHINE SO FAR, SO IT MAY WORK OR NOT WORK AS INTENDED ON OTHER OPERATING SYSTEMS.
]]
-------------------------------
-- DEFINE YOUR SETTINGS HERE --
-------------------------------
-- Add all your achievement conditions to this table. The conditions have to be set up in the editor with an
-- initial value of false (no combined conditions). Make sure their names are unique throughout the project.
local achvm_conditions = {
"achievement_condition_1",
"achievement_condition_2",
"achievement_condition_3"
}
-- Enter a random string of any length
local secret_key = "gKEA82cajZS5Z8vd"
-- You may change the filename to store the achievements
local achvm_file = "achvm.dat"
-- If you would like to save the achievements in the config.ini instead of in a separate file,
-- set the INI mode to true. In that case you have to read and write the config.ini by yourself
-- and use the set_achievements() and get_achievements() functions in your config.ini script.
local ini_mode = false
--------------------------------------------------------
-- USUALLY NO NEED TO CHANGE ANYTHING BELOW THIS LINE --
--------------------------------------------------------
local achvm_hashed_conds = {}
-- Regular mode: Call this function after loading a game
function load_achievements()
if not ini_mode then
local read_file = io.open(localAppDir .. achvm_file, "r")
local saved_achvm = {}
if read_file then
for line in read_file:lines() do
line = string.gsub(line, '\r', '')
saved_achvm[line] = line
end
read_file:close()
for k,v in pairs(achvm_hashed_conds) do
if(saved_achvm[k] ~= nil) then
Conditions[v].Value = true
else
Conditions[v].Value = false
end
end
end
end
end
-- Regular mode: Call this function after you changed one of the achievement conditions
function save_achievements()
if not ini_mode then
local write_file = io.open(localAppDir .. achvm_file, "w")
if write_file then
for k,v in pairs(achvm_hashed_conds) do
if(Conditions[v].Value) then
write_file:write(k .. "\n")
end
end
write_file:close()
end
end
end
-- INI mode: Pass the achievements string from the config.ini file to this function to set the achievement conditions accordingly
function set_achievements(ini_str)
if ini_mode then
ini_str = string.lower(ini_str)
if string.sub(ini_str, 1, 15) == "achievements = " then
local achvm_str = string.sub(ini_str, 16)
local saved_achvm = {}
if achvm_str ~= "" then
for i in string.gmatch(achvm_str, "([^|]+)") do
saved_achvm[i] = i
print(i)
end
end
for k,v in pairs(achvm_hashed_conds) do
if(saved_achvm[k] ~= nil) then
Conditions[v].Value = true
else
Conditions[v].Value = false
end
end
end
end
end
-- INI mode: Call this function to get the achievements string to save in the config.ini file
function get_achievements()
if ini_mode then
local get_achvm = {}
for k,v in pairs(achvm_hashed_conds) do
if(Conditions[v].Value) then
table.insert(get_achvm, k)
end
end
if get_achvm ~= nil then
return "# Little achievements\nAchievements = " .. table.concat(get_achvm, "|")
end
return ""
end
end
-- Try to create a unique hash to avoid cheating
function obfuscate_cond(cond)
local system_info = system.systemInfo()
local string = secret_key
if system_info.cpuModel ~= nil then string = string .. system_info.cpuModel end
if system_info.gpu ~= nil then string = string .. system_info.gpu end
if system_info.os ~= nil then string = string .. system_info.os end
if system_info.ram ~= nil then string = string .. system_info.ram end
string = string .. localAppDir .. cond
return sha1(string)
end
-- Initialize the achievements
function achievements_init()
for k,v in pairs(achvm_conditions) do
achvm_hashed_conds[ obfuscate_cond(v) ] = v
end
end
achievements_init()
if not ini_mode then
load_achievements()
end
--[[
MIT License
Copyright 2023 Einzelkämpfer
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
GameLoaded-Skript
-- Gets executed right after loading a savegame
function onEngineEvent(event, path)
if event == "LoadingSavegameSuccess" then
load_achievements()
end
end
registerEventHandler("engineEvent", "onEngineEvent")
Ressourcen
| Name | Beschreibung |
|---|---|
| Kleine Erfolge 1.2.zip | Ein funktionierendes Beispiel für das Skript. Für die enthaltenen .ved-Dateien brauchst du Visionaire Studio 5.2+. |