diff --git a/v0.7.1 b/v0.7.1 new file mode 100644 index 0000000..44853a5 --- /dev/null +++ b/v0.7.1 @@ -0,0 +1,317 @@ +// Sammelsystem - Giver v0.7.1 + +// "4CGS-Init" in die Objektbeschreibung eintragen, um ein Objekt zu initialsieren oder die Werte neu zu setzen + +integer m_num_slots = 8; // ANzahl Slots, die der Spieler hat +integer m_max_slots = 8; // Anzahl mx. erreichbare Slots +key klicker = NULL_KEY; // Wer hat geklickt? +string m_itemName = "navi_wasserbeutel"; // Name für den Pfad, unter dem dieses Objekt auf dem Server verwaltet wird. +string m_displayName = "Na'vi Wasserbeutel"; // Angezeigter Name des Sammelobjektes +string m_desc = "Ein voller Na'vi Wasserbeutel."; // Kurzbeschreibung +string m_item_weight = "1.5"; // Gewicht des Gegenstandes (für max. Ztaglast benötigt) +string m_desc_long = "Wasserbeutel werden für den Transport von Flüssigkeiten benutzt. Sie fassen ca. 1/2 Liter Wasser. Die Na'vi stellen diese Behälter aus verschiednen Ledersorten, Riemen und Hölzern her. "; // Anschauen Text +string m_eat = "Trinken"; // Button-Text für Aktion +string m_watch = "Anschauen"; // Button-Text, um die lange Beschreibung zu lesen (Anschauen). +string m_use = "Anwenden"; // Button-Text, wenn Item auf jmd. angewendet wird, +string m_xp = "5"; // XP, die man fürs Benutzen bekommt. +string m_xp_collect = "2"; // XP, die man fürs Sammlen bekommt. +string m_hp = "5"; // Wieviel HP werde abgezogen? (Negative Werte addieren HP) +string m_food = "0"; // Wieviel Nahrung wird dazu addiert? (Negative Werte ziehen Nahrung ab) +string m_water = "50"; // Wieviel Wasser wird dazu addiert? (Negative Werte ziehen Wasser ab) +float m_range = 5.0; // Wie weit darf der Avatar vom Giver entfernt sein (1 ... 96m, 0 = Beliebig) +integer m_time_fix = 0; // Zeit, wie lange das Objekt unsichtbar ist (in Sekunden). Wenn 0 = Deaktiviert +integer m_time_rnd = 0; // Zufällige Zeit, die der Fixzeit hinzuaddiert wird und die zwischen 0 und dem hier angegebenen Wert liegt. +integer m_rnd = -1; // Wenn > 1, wird eine zufällige Anzahl von 1 ... m_rnd gesammelt. Wenn Wert negativ, dann diese Anzahl dazu rechnen. +integer m_minlevel = 0; // Wenn Sammler einen kleineren Level hat, entscheidet der Zufall, ob er das Itam bekommt. +integer m_isunique = FALSE; // Falls TRUE, wird beim "Entsorgen" abgefragt, ob man das möchte. + +// #################################################################################################################################### + +integer m_num = 0; // Anzahl gesammelter Items +float m_weight_total = 0; // Gesamtgewicht gesammelter Items +string m_toofar = "Du bist zu weit entfernt, um '{0}' zu sammeln."; +string m_lang_noslot = "Du hast keinen Inventar Slot mehr frei!"; +string m_lang_collected = "Du hast {0} x {1} genommen und {2} Erfahrungspunkte (XP) dazu bekommen."; +string m_lang_used = "Du hast {0} benutzt und {1} Erfahrungspunkte (XP) dazu bekommen."; +string m_lang_wronggroup = "Entweder Du hast nicht die richtige Gruppe aktiviert oder '{0}' hat nicht die Landgruppe."; +string m_lang_init = "Das Objekt '{0}' [Itemname: '{1}'] ] wurde initialisiert."; +string m_lang_tooheavy = "Das ist zu schwer für Dich. Du kannst nur max. {0}kg tragen."; +string m_lang_level_too_low = "Um '{0}' zu sammlen, musst Du mindestens Level {1} erreichen. Du bekommst aber dennoch {2} Erfahrungspunkte (XP) dazu."; + + +default +{ + state_entry() + { + llSetAlpha(255, ALL_SIDES); + if(llGetObjectDesc() == "4CGS-Init" || !osCheckDataValue("itam." + m_itemName)) + { + llSetObjectDesc(""); + llOwnerSay(osFormatString(m_lang_init, [m_displayName, m_itemName])); + list _dataStorage = getDataListFromDataStorage("item." + m_itemName); + _dataStorage = setDataEntryInDataList(_dataStorage, "image", llGetInventoryKey(llGetInventoryName(INVENTORY_TEXTURE, 0))); + _dataStorage = setDataEntryInDataList(_dataStorage, "displayname", m_displayName); + _dataStorage = setDataEntryInDataList(_dataStorage, "beschreibung", m_desc); + _dataStorage = setDataEntryInDataList(_dataStorage, "unique", m_isunique); + _dataStorage = setDataEntryInDataList(_dataStorage, "weight", m_item_weight); + + _dataStorage = setDataEntryInDataList(_dataStorage, "actions", "eat;watch;futtern"); + + _dataStorage = setDataEntryInDataList(_dataStorage, "actions.eat.displayname", m_eat); + _dataStorage = setDataEntryInDataList(_dataStorage, "actions.eat.consume", "TRUE"); + _dataStorage = setDataEntryInDataList(_dataStorage, "actions.eat.setTarget", "FALSE"); + _dataStorage = setDataEntryInDataList(_dataStorage, "actions.eat.tasks", "addFood:" + (string)m_food + ";addWater:" + (string)m_water + ";addXP:" + (string)m_xp + ";addHP:" + (string)m_hp); + + _dataStorage = setDataEntryInDataList(_dataStorage, "actions.watch.displayname", m_watch); + _dataStorage = setDataEntryInDataList(_dataStorage, "actions.watch.consume", "FALSE"); + _dataStorage = setDataEntryInDataList(_dataStorage, "actions.watch.setTarget", "FALSE"); + _dataStorage = setDataEntryInDataList(_dataStorage, "actions.watch.tasks", "say:" + m_desc_long); + + _dataStorage = setDataEntryInDataList(_dataStorage, "actions.futtern.displayname", m_use); + _dataStorage = setDataEntryInDataList(_dataStorage, "actions.futtern.consume", "TRUE"); + _dataStorage = setDataEntryInDataList(_dataStorage, "actions.futtern.setTarget", "TRUE"); + _dataStorage = setDataEntryInDataList(_dataStorage, "actions.futtern.tasks", "addFood:" + (string)m_food + ";addWater:" + (string)m_water + ";addHP:" + (string)m_hp + ";addXP:" + (string)m_xp); + + saveDataListToDataStorage(_dataStorage, "item." + m_itemName); + } + } + + touch_start(integer i) + { + klicker = llDetectedKey(0); + list _dataStorage = getDataListFromDataStorage("game.hud.player." + llDetectedKey(0)); + integer _slot = getNextFreeInventorySlot(_dataStorage, m_itemName); + integer _level = llList2Integer(calcLevelData(_dataStorage), 0); + + m_num = 1; + if(m_rnd > 1) + m_num = (integer)(llFrand(m_rnd) + 1); + else if (m_rnd < 0) + m_num = -m_rnd; + m_weight_total = (float)m_num * (float)m_item_weight; + + if(!llSameGroup(klicker)) + { + llRegionSayTo(klicker, 0, osFormatString(m_lang_wronggroup, [m_displayName])); + return; + } + + if(getMaxPlayerWeight(_dataStorage) < calcPlayerWeight(_dataStorage) + m_weight_total) + { + llOwnerSay(osFormatString(m_lang_tooheavy, [llGetSubString((string)getMaxPlayerWeight(_dataStorage), 0, llSubStringIndex((string)getMaxPlayerWeight(_dataStorage), ".") + 2)])); + return; + } + + if(_slot == 0) + { + llRegionSayTo(klicker, 0, m_lang_noslot); + return; + } + + if(m_range != 0.0) + llSensor("",klicker, AGENT_BY_LEGACY_NAME, m_range, PI); + else + state sammeln; + } + + sensor(integer x) + { + state sammeln; + } + + no_sensor() + { + llInstantMessage(klicker, osFormatString(m_toofar, [m_displayName])); + } + + timer() + { + llSetTimerEvent(0); + llResetScript(); + } + + changed(integer change) + { + if(change & (CHANGED_REGION_RESTART | CHANGED_INVENTORY)) + llResetScript(); + } +} + +// ################################################################################################### + +state sammeln +{ + state_entry() + { + llOwnerSay((string)m_num); + list _dataStorage = getDataListFromDataStorage("game.hud.player." + klicker); + integer _slot = getNextFreeInventorySlot(_dataStorage, m_itemName); + integer _level = llList2Integer(calcLevelData(_dataStorage), 0); + integer _xp = (integer)getDataEntryFromDataList(_dataStorage, "stats.xp"); + + if(_level >= (integer)m_minlevel) + { + _dataStorage = setDataEntryInDataList(_dataStorage, "stats.xp", _xp + (m_num * (integer)m_xp_collect)); + _dataStorage = setDataEntryInDataList(_dataStorage, "inventar.slot." + _slot, m_itemName); + _dataStorage = setDataEntryInDataList(_dataStorage, "inventar.slot." + _slot + ".count", getItemCountFromSlot(_dataStorage, _slot) + m_num); + llRegionSayTo(klicker, 0, osFormatString(m_lang_collected, [(string)m_num, m_displayName, (string)(m_num * (integer)m_xp_collect)])); + } + else + { + //m_num = 0; + _dataStorage = setDataEntryInDataList(_dataStorage, "stats.xp", _xp + (integer)m_xp_collect); + llRegionSayTo(klicker, 0, osFormatString(m_lang_level_too_low, [m_displayName, m_minlevel, (string)m_xp_collect])); + } + + saveDataListToDataStorage(_dataStorage, ("game.hud.player." + klicker)); + llSay((integer)getDataEntryFromDataList(_dataStorage, "channel"), "gamecommand;reload"); + + if(m_time_fix + m_time_rnd == 0) + state default; + else + { + llSetAlpha(0, ALL_SIDES); + llSetTimerEvent(m_time_fix + (integer)llFrand(m_time_rnd)); + } + } + + timer() + { + llSetTimerEvent(0); + llResetScript(); + } + + changed(integer change) + { + if(change & (CHANGED_REGION_RESTART | CHANGED_INVENTORY)) + llResetScript(); + } +} + +// ################################################################################################### + +integer getNextFreeInventorySlot(list _dataStorage, string _itemName) +{ + integer _freeSlot = 0; + integer _currentSlot; + for(_currentSlot = 1; _currentSlot <= m_num_slots; ++_currentSlot) + { + if(getDataEntryFromDataList(_dataStorage, "inventar.slot." + _currentSlot) == _itemName) + return _currentSlot; + + if(getDataEntryFromDataList(_dataStorage, "inventar.slot." + _currentSlot) == "") + if(_freeSlot == 0) + _freeSlot = _currentSlot; + } + + return _freeSlot; +} + +integer getItemCountFromSlot(list _dataStorage, integer _slot) +{ + return (integer)getDataEntryFromDataList(_dataStorage, "inventar.slot." + _slot + ".count"); +} + +list getDataListFromDataStorage(string _storage) +{ + return llCSV2List(osGetDataValue(_storage)); +} + +saveDataListToDataStorage(list _dataList, string _storage) +{ + string _csv = llList2CSV(_dataList); + osSetDataValue(_storage, _csv); +} + +integer checkDataEntryInDataList(list _dataList, string _key) +{ + integer _inListPosition = llListFindList(_dataList, [_key]); + + if(_inListPosition == -1) + return FALSE; + + return TRUE; +} + +string getDataEntryFromDataList(list _dataList, string _key) +{ + integer _inListPosition = llListFindList(_dataList, [_key]); + + if(_inListPosition == -1) + return ""; + + return llList2String(_dataList, _inListPosition + 1); +} + +list setDataEntryInDataList(list _dataList, string _key, string _value) +{ + integer _inListPosition = llListFindList(_dataList, [_key]); + + if(_inListPosition == -1) + { + _dataList += [_key, _value]; + return _dataList; + } + + return llListReplaceList(_dataList, [_value], _inListPosition + 1, _inListPosition + 1); +} + +integer calcPlayerWeight(list _userStorage) +{ + integer _currentSlot; + integer _currentWeight = 0; + for(_currentSlot = 1; _currentSlot <= m_num_slots; ++_currentSlot) + { + if(getDataEntryFromDataList(_userStorage, "inventar.slot." + _currentSlot) != "") + { + string _itemName = getDataEntryFromDataList(_userStorage, "inventar.slot." + _currentSlot); + list _itemData = getDataListFromDataStorage("item." +_itemName); + + integer _itemCount = getItemCountFromSlot(_userStorage, _currentSlot); + integer _itemWeight = (integer)getDataEntryFromDataList(_itemData, "weight"); + + _currentWeight = _currentWeight + (_itemCount * _itemWeight); + } + } + + return _currentWeight; +} + +list calcLevelData(list _dataStorage) +{ + list _dataStore = getDataListFromDataStorage("game.hud"); + integer _xpLevelStep = (integer)getDataEntryFromDataList(_dataStore, "stats.levels.firstStep"); + integer _maxlevel = (integer)getDataEntryFromDataList(_dataStore, "stats.levels.maxlevel"); + + float _xpLevelStepMultiplier = (float)getDataEntryFromDataList(_dataStore, "stats.levels.multiplier"); + integer _currentXP = (integer)getDataEntryFromDataList(_dataStorage, "stats.xp"); + integer _currentLevel = 0; + + integer _xpNeedForNextLevel = _xpLevelStep * _xpLevelStepMultiplier; + + + while(_currentXP > _xpNeedForNextLevel) + { + if(_currentLevel <= _maxlevel) + { + _currentLevel = _currentLevel + 1; + _currentXP = _currentXP - _xpNeedForNextLevel; + _xpNeedForNextLevel = (_xpNeedForNextLevel * _xpLevelStepMultiplier); + } + } + + return [_currentLevel, (integer)_currentXP, _xpNeedForNextLevel]; +} + +float getMaxPlayerWeight(list _dataStorage) +{ + list _dataStore = getDataListFromDataStorage("game.hud"); + integer _maxweight = (integer)getDataEntryFromDataList(_dataStore, "stats.levels.maxweight"); + float _xpMultiplier = (float)getDataEntryFromDataList(_dataStore, "stats.levels.multiplier"); + + list _levelData = calcLevelData(_dataStorage); + integer _playerLevel = llList2Integer(_levelData, 0) + 1; + + float _playerMaxWight = _maxweight * (_playerLevel * _xpMultiplier); + return _playerMaxWight; +} \ No newline at end of file