Welcome to U.A.C. [O.S.A.]
login / register
Status: Guest
Архивы форума | iddqd.ru
Wolf 3D
ПравилаПравила ПоискПоиск
18+
Тема для новичков. Вопросы по маппингу/моддингу - любые! Пред.  1, 2, 3 ... 158, 159, 160 ... 198, 199, 200  След.
   Список разделов - Флуд и устаревшие темы - Тема для новичков. Вопросы по маппингу/моддингу - любые!Ответить
АвторСообщение
MyNameIs
= 1st Lieutenant =
Next rank: - Captain - after 60 points
2030

Doom Rate: 2.05

Posts quality: +876
Ссылка на пост №3161 Отправлено: 21.04.18 09:17:00
Void Weaver
ну ты же не сказал, кого нужно замедлять, я и думал, что кого-то одного конкретного.
1 1 1
Void Weaver
= Captain =
Next rank: - Major - after 144 points
2496

Doom Rate: 1.82

Posts quality: +807
Ссылка на пост №3162 Отправлено: 21.04.18 18:44:15
А что если для монстров записать что-то типа:

1) if (SetActivator(0, aaptr_target) && (ClassifyActor(0) & (actor_monster)) && (ClassifyActor(0) & actor_alive));
2) чек actorProperty "скорость" цели
3) var int "x" = aprop_speed возвращённая чеком
4) счётчик while\until\for y<x; y++
5) SetActorProperty(0, aprop_speed, "y"), где int "y" - значение до которого снижена скорость (ну или нулевая)

Как это можно записать? Ну если это не полная ахинея офк.
И кстати перед этим стоит добавить If(SetActivator(0, AAPTR_TARGET)) с развилкой на разные скрипты ACS_NamedExecuteWithResult("monslow\playerslow")).
1 9 1
Hypercube
= UAC Gunner =
Next rank: - Corporal - after 18 points
62

Doom Rate: 1.88

Posts quality: +14
Ссылка на пост №3163 Отправлено: 24.04.18 23:25:42
Назрел вопрос: есть ли возможность в DooM Builder сделать так, чтобы во время использовании ВИЗУАЛЬНОЙ моды яркость секторов НЕ отображалась бы и была максимальной всегда? А то не очень удобно работать с тёмными помещениями.

Всё, разобрался - надо в визуальной моде нажать клавишу B. Оставлю тут, так как может кому-то пригодиться.
Void Weaver
= Captain =
Next rank: - Major - after 144 points
2496

Doom Rate: 1.82

Posts quality: +807
Ссылка на пост №3164 Отправлено: 24.04.18 23:32:02
А мобам нельзя выдавать пауэрапы? Пробовал раздать Speed и че-т не пашет.
1 9 1
Anto96WS
= Master Corporal =
Next rank: - Sergeant - after 9 points
281

Doom Rate: 1.77

Posts quality: +88
Ссылка на пост №3165 Отправлено: 25.04.18 20:53:14
Где можно достать имя автора ресурса, использованного в своем ваде?
JSO x
- 2nd Lieutenant -
Next rank: = 2nd Lieutenant = after 142 points
1298

Doom Rate: 2.29

Posts quality: +698
Ссылка на пост №3166 Отправлено: 25.04.18 20:57:36
Anto96WS, на ZDoom-форуме, на "Official ZDoom Discord"-сервере поспрашивай. Ещё может быть, что человек, когда ресурс делал, в файл свой псевдоним внёс (в PhotoShop'е, например).

Void Weaver, выдавать-то Powerup'ы можно, они у монстров в инвентаре будут. Другое дело, что никаких эффектов не дадут, только на игроков действуют.

Рейтинг сообщения: +1, отметил(и): alekv
2 7 1
Anto96WS
= Master Corporal =
Next rank: - Sergeant - after 9 points
281

Doom Rate: 1.77

Posts quality: +88
Ссылка на пост №3167 Отправлено: 25.04.18 21:02:37
JSO x:
выдавать-то Powerup'ы можно


О. Пока не поздно спрошу

Недавно мне надо было дать предмету предмет. Возможно?
camper
- Master Sergeant -
Next rank: = Master Sergeant = after 28 points
432

Doom Rate: 1.43

Posts quality: +253
Ссылка на пост №3168 Отправлено: 25.04.18 23:02:19
Пытался немного изменить одну карту в GZDoom Builder, первый раз сегодня начал разбираться и как-то раньше не задумывался о структуре карт в думе. После cube 2 sauerbraten это жесть какая-то. Снимаю шляпу перед всеми думовскими мапперами. Никто не знает, может разрабы какого-нибудь порта будут уходить от секторов к кубам, как в sauerbraten? Или это принципиально невозможно.
ZZYZX
- UAC Commissar -
Next rank: = UAC Commissar = after 16 pointsМодератор форума
6284

Doom Rate: 1.65

Posts quality: +1630
Ссылка на пост №3169 Отправлено: 25.04.18 23:23:30
Не будут. После простого и понятного маппинга под дум маппинг под Sauerbraten — мучение.

Рейтинг сообщения: +1, отметил(и): alekv
2 2 1
YURA_111
UAC Sergeant Major
Next rank: Chief Petty Officer after 86 points
764

Doom Rate: 1.98

Posts quality: +136
Ссылка на пост №3170 Отправлено: 25.04.18 23:52:11
Void Weaver:
А мобам нельзя выдавать пауэрапы?


Можно. Мой (безскриптовый) пример..:
https://www.youtube.com/watch?v=b3cuO-bi-GA&feature=youtu.be

JSO x:
выдавать-то Powerup'ы можно, они у монстров в инвентаре будут.


В том то и дело - давать монстрам нужно НЕ инвентарь и НЕ В инвентарь...

Рейтинг сообщения: +1, отметил(и): Void Weaver
Void Weaver
= Captain =
Next rank: - Major - after 144 points
2496

Doom Rate: 1.82

Posts quality: +807
Ссылка на пост №3171 Отправлено: 26.04.18 00:10:02
YURA_111, прям с языка снял.
Как раз только что скрафтил импу пауэрап "брони":

Скрытый текст:

Actor ArmorGiver : PowerupGiver
{
    Inventory.MaxAmount 0
    Powerup.Duration 0x7FFFFFFF
    +Inventory.AutoActivate
    +Inventory.AlwaysPickup
    Powerup.Type "Armor"
}

Actor PowerArmor : PowerProtection
{
        DamageFactor "Normal", 0.0
	DamageFactor "None", 0.0
	DamageFactor "Melee", 0.0
}

Офк вызывается через кастоминвентори, и прекрасно работает.
Видимо просто не все типы натив пауэрапов в декоре действуют на мобов.

Anto96WS:
Недавно мне надо было дать предмету предмет. Возможно?
А можно поподробнее о природе "предметов"? Что именно кому\чему хотел выдать?

Рейтинг сообщения: +1, отметил(и): JSO x
1 9 1
camper
- Master Sergeant -
Next rank: = Master Sergeant = after 28 points
432

Doom Rate: 1.43

Posts quality: +253
Ссылка на пост №3172 Отправлено: 26.04.18 11:57:13
ZZYZX:
Не будут. После простого и понятного маппинга под дум маппинг под Sauerbraten — мучение.

В этом правда есть. Однако и в гздуме есть сложности с построением стен вокруг 3д полов, насколько я понимаю.
Правильно я понимаю, что стены надо строить секторами, а это значит, что 3д крыши у здания не будет, крыша будет совмещена с ceiling. Вот если бы наряду с секторами были бы еще и блоки, это было бы проще.
И в догонку, а можно использовать в качестве стен 3д простые модели в мд3 или мд2?

Добавлено спустя 23 минуты 12 секунд:

Дошло. 3Д полы это и есть 3д блоки, можно попробовать прямо из них сделать стены, если вытянуть по вертикали и сжать по горизонтали.
+Ku6EPyXOBEPTKA+
- Major -
Next rank: = Major = after 47 pointsМодератор форума
2893

Doom Rate: 2.05

Posts quality: +1434
Ссылка на пост №3173 Отправлено: 26.04.18 12:43:04
camper
Немного не понял про 3д что там не так будет? Всё довольно просто строится - сектор, его размеры - это и есть поверхность 3д пола, вспомогательный сектор с линией указывающей на tag сектора - это 3д пол в физическом смысле, то есть высота, яркость под ним, свойства, текстура, рендер внутри при необходимости.
Скрытый текст:


Внешний 3д сектор:

Внутренний 3д сектор:


Поэтому особо трудностей нет в построении. Если есть сектор, то сразу можно задать tag и указать в вспомогательном. Если нет, то просто провести его и сделать ту же процедуру.

camper:
Дошло. 3Д полы это и есть 3д блоки, можно попробовать прямо из них сделать стены, если вытянуть по вертикали и сжать по горизонтали.

Да. Но проблема в том, что иногда два блока могут быть на одной вертикальной оси, но в разных направлениях, из-за чего в горизонтальной плоскости (или вид сверху, чтобы было понятнее) образуются две пересечённые фигуры и это придётся учитывать. Для наглядности смастерил вот такую картинку:


Кстати, как маппер в GoldSrc и Source скажу, что блоками значительно сложнее мапить простые комнаты. В думе достаточно провести от края до края двумя кликами, чтобы сделать квадратную комнату, а в сорсах стены имеют толщину, да ещё и не зависят от высоты, а значит надо сделать 1 фигуру, внутри которой надо сделать другую и вырезать, или воспользоваться функцией (уже не помню как называется, правда.. давно не маппил) которая автоматом оставляет полость внутри с постоянной толщиной стенок.
Зато в многро этажных и сложных конструкциях можно отыграться, так как позволяет не просто делать объёмные фигуры любой формы, но и не сковывает в пространстве.

Рейтинг сообщения: +3, отметил(и): alekv, DOOMGABR, camper
2 1 7
Anto96WS
= Master Corporal =
Next rank: - Sergeant - after 9 points
281

Doom Rate: 1.77

Posts quality: +88
Ссылка на пост №3174 Отправлено: 26.04.18 14:32:33
Void Weaver:
А можно поподробнее о природе "предметов"? Что именно кому\чему хотел выдать?


Выкидываемому рюкзаку предметы, которые в нем были

Рейтинг сообщения: +1, отметил(и): camper
Void Weaver
= Captain =
Next rank: - Major - after 144 points
2496

Doom Rate: 1.82

Posts quality: +807
Ссылка на пост №3175 Отправлено: 26.04.18 22:52:50
Подозреваю что без скриптинга не обойтись.
В Kyle's DRPG как раз существовали контейнеры с собственным интерактивным инвентарём, правда они не были портативными но вероятно это так же поправимо скриптом.
Актор на базе SwitchableDecoration, типа: ящик заюзали\не заюзали. Creating decorations that can be (de)activated

Декор DRPG ящика:
Скрытый текст:

actor DRPGCrate : SwitchableDecoration
{
    var int user_id;
    var int user_firewall;
    
    Radius 16
    Height 8
    
    -SOLID
    +USESPECIAL
    
    Activation THINGSPEC_ThingActs | THINGSPEC_ThingTargets | THINGSPEC_Switch | THINGSPEC_Deactivate
    
    Scale 0.75
    
    States
    {
    Spawn:
        TNT1 A 0 NoDelay ACS_NamedExecuteAlways("InitCrate", 0)
        TNT1 A 1
    LoopPick:
        TNT1 A 0 A_JumpIf(user_firewall == 0, "LoopNormal")
        TNT1 A 0 A_JumpIf(user_firewall == 1, "LoopFirewall")
        Stop
    Normal:
        TNT1 A 0 A_RemoveChildren(true)
        TNT1 A 0 A_PlaySound("crate/loop1", CHAN_6, 0.75, true, 1.25)
    LoopNormal:
        CRAT ABCDEFGHIJKLMNOPQRSTUVWXYZ 2 Bright
        CRA2 ABCDEFGHIJKLMNOPQRSTUVWXYZ 2 Bright
        CRA3 A 2 Bright
        Loop
    Firewall:
        TNT1 A 0 A_PlaySound("crate/loop2", CHAN_6, 0.75, true, 1.25)
        TNT1 A 0 A_SpawnItemEx("DRPGCrateFirewallIcon", 0, 0, 0, 0, 0, 0, 0, SXF_SETMASTER)
    LoopFirewall:
        CRAT ABCDEFGHIJKLMNOPQRSTUVWXYZ 1 Bright
        CRA2 ABCDEFGHIJKLMNOPQRSTUVWXYZ 1 Bright
        CRA3 A 1 Bright
        Loop
    Active:
    Inactive:
        TNT1 A 0 ACS_NamedExecuteAlways("UseCrate", 0, user_id)
        Goto LoopPick
    Empty:
        TNT1 A 0 A_StopSound(CHAN_6)
        TNT1 A 0 A_PlaySound("crate/off", CHAN_7, 0.75, false, 1.25)
        TNT1 A 0 A_ChangeFlag("USESPECIAL", false)
        CRA3 B -1
        Stop
    Explode:
        TNT1 A 0 A_ChangeFlag("USESPECIAL", false)
        TNT1 A 0 A_RemoveChildren(true)
        TNT1 A 0 A_PlaySound("weapons/rocklx", CHAN_7, 2.0, false, 0.5)
        TNT1 A 0 A_Explode
        MISL BCD 6 Bright
        Stop
    }
}

actor DRPGCrateFirewallIcon
{
    var int user_step;
    
	-SOLID
    +ISMONSTER // This is fucking retarded.jpg
	+NOINTERACTION
	+NOGRAVITY
    +FORCEYBILLBOARD
    +FLOATBOB
	
	RenderStyle Add
    
    States
    {
    Spawn:
    FadeLoop:
        CRFW A 1 Bright
        TNT1 A 0 A_Warp(AAPTR_MASTER, 0, 0, 72, 0, WARPF_NOCHECKPOSITION | WARPF_COPYINTERPOLATION)
        TNT1 A 0 A_SetTranslucent(0.5 + (0.25 * Sin(user_step)), 1)
        TNT1 A 0 A_SetUserVar("user_step", user_step + 10.285714)
        TNT1 A 0 A_Warp(AAPTR_MASTER, 0, 0, 0, 0, WARPF_NOCHECKPOSITION | WARPF_TESTONLY, "FadeLoop")
        Loop
    }
}

Скрипт DRPG ящика:
Скрытый текст:

#include "Defs.h"
#include "RPG.h"

#include "Crate.h"
#include "ItemData.h"
#include "Stats.h"
#include "Utils.h"

str const CrateRarityNames[MAX_DIFFICULTIES] =
{
    "\CcBasic",
    "\CjCommon",
    "\CdUncommon",
    "\CdSuperior",
    "\CnRare",
    "\CnVery Rare",
    "\CiElite",
    "\CtLegendary",
    "\CfSupreme"
};

RPGMap int CrateID = 0;
RPGMap CrateInfo Crates[CRATE_MAX];

NamedScript Type_OPEN void CrateLoop()
{
    while (true)
    {
        for (int i = 0; i < CrateID; i++)
        {
            // Hacking cooldown timer handling
            if (Crates[i].HackingCooldown > 0)
                Crates[i].HackingCooldown--;
        
            // Supply Drop spawned crates should never have a firewall
            if (Crates[i].SupplyDrop && Crates[i].Firewall)
            {
                Crates[i].Firewall = false;
                SetActorState(Crates[i].TID, "Normal");
            }
        }
        
        Delay(1);
    }
}

NamedScript DECORATE void InitCrate()
{
    int TID = UniqueTID();
    int Amount = 3;
    int LuckMod = (AveragePlayerLevel() + AveragePlayerLuck()) / 20;
    int Rarity = 0;
    int Firewall = 0;
    
    if (CrateID >= CRATE_MAX)
    {
        Log("\CgERROR:\C- Maximum Crate ID exceeded!");
        Thing_Remove(0);
        return;
    }
    
    // Calculate Rarity
    for (int i = Rarity; i < MAX_DIFFICULTIES - 1; i++)
        if (Random(0, (MAX_DIFFICULTIES + (MAX_DIFFICULTIES / 3)) - LuckMod) <= 0)
            Rarity++;
    if (Rarity < 0) // Make sure the Rarity still isn't -1, or else bad things will happen
        Rarity = 0;
    if (Rarity > MAX_DIFFICULTIES - 1)
        Rarity = MAX_DIFFICULTIES - 1;
    
    // Calculate Amount
    for (int i = Amount; i < CRATE_MAX_ITEMS; i++)
        if (Random(0, i) <= 0)
            Amount++;
    Amount += PlayerCount() - 1;      // Add +1 per extra player in-game
    if (Amount > CRATE_MAX_ITEMS - 1) // Make sure we don't overflow
        Amount = CRATE_MAX_ITEMS;
    
    // Calculate Firewall odds
    Firewall = Rarity * 10;
    if (Firewall <= 10)
        Firewall = 10;
    if (Firewall > 100)
        Firewall = 100;
    
    // Setup Crate
    Crates[CrateID].Firewall = (Random(0, 100) <= Firewall);
    Crates[CrateID].TID = TID;
    Crates[CrateID].Amount = Amount;
    Crates[CrateID].Rarity = Rarity;
    Crates[CrateID].Hacking = -1;
    Thing_ChangeTID(0, TID);
    SetUserVariable(0, "user_id", CrateID);
    SetUserVariable(0, "user_firewall", (int)Crates[CrateID].Firewall);
    if (Crates[CrateID].Firewall)
        SetActorState(0, "Firewall");
    else
        SetActorState(0, "Normal");
    
    for (int x = 0; x < CRATE_MAX_ITEMS; x++)
    {
        Crates[CrateID].Active[x] = false;
        Crates[CrateID].Item[x] = NULL;
    }
    
    CrateID++;
}

NamedScript DECORATE void UseCrate(int ID)
{
    // Hackity hacks so you can't open the crate yet if the rewards list is not done being generated
    if (!RewardsInit) return;
    
    SetActivator(GetActorProperty(0, APROP_TargetTID));
    
    // Hack for if you somehow activate a crate while you're hacking another one
    if (Player.CrateHacking) return;
    
    // Someone else is hacking the crate
    if (Crates[ID].Hacking >= 0)
    {
        if (Crates[ID].Hacking != PlayerNumber())
        {
            PrintError(StrParam("%tS\C- is already hacking an item in this crate", Crates[Player.CrateID].Hacking + 1));
            ActivatorSound("menu/error", 127);
        }
        
        return;
    }
    
    // Check if you're in a menu
    if (Player.InMenu || Player.InShop || Player.CrateOpen) return;
    
    // Check if the crate is empty
    if (Crates[ID].Generated && CrateEmpty(ID)) return;
    
    // Check if the crate is firewalled, if so, initiate hacking
    if (Crates[ID].Firewall)
    {
        if (Crates[ID].HackingCooldown > 0)
        {
            PrintError(StrParam("Security Lockdown Triggered\n\nYou must wait %S before reattemtping the hack", FormatTime(Crates[ID].HackingCooldown)));
            ActivatorSound("menu/error", 127);
        }
        else
        {
            Player.CrateID = ID;
            CrateHack();
        }
        return;
    }
    
    // Generate the crate contents
    if (!Crates[ID].Generated)
    {
        GenerateCrate(ID, Crates[ID].Amount);
        Crates[ID].Generated = true;
    }
    
    Player.CrateOpen = true;
    Player.CrateID = ID;
    Player.CrateIndex = 0;
    
    ActivatorSound("crate/open", 127);
    
    Delay(1);
    
    while (Player.CrateOpen)
    {
        SetHudSize(GetActivatorCVar("drpg_menu_width"), GetActivatorCVar("drpg_menu_height"), true);
        
        SetPlayerProperty(0, 1, PROP_TOTALLYFROZEN);
        
        DrawCrate();
        CrateInput();
        
        Delay(1);
    }
    
    SetPlayerProperty(0, 0, PROP_TOTALLYFROZEN);
}

NamedScriptSync bool GenerateCrateNodes(CrateInfo RPGMap *Crate)
{
    int StopCount = 4000;
    
    while (Crate->GenType < NODE_MAX)
    {
        bool Conflict = false;
        int Start = Random(0, 300 - 12);
        int End = 4 * Random(1, 2);
        
        // Make sure we don't generate over the max amount of allowed node types
        if (Crate->GenNodes[Crate->GenType] >= Crate->NodeMax[Crate->GenType])
        {
            Crate->GenType++;
            continue;
        }
        
        // Make sure there are no node conflicts
        for (int i = 0; i < MAX_NODES; i++)
            if (Crate->Nodes[i].Active && !Conflict)
                for (int j = 0; j < End; j++)
                    if (Start + j >= Crate->Nodes[i].Start && Start + j <= Crate->Nodes[i].Start + Crate->Nodes[i].End)
                    {
                        Conflict = true;
                        break;
                    }
        
        // Get new coordinates due to a conflict
        if (Conflict)
            continue;
        
        // Setup Node
        Crate->Nodes[Crate->GenTotal].Active = true;
        Crate->Nodes[Crate->GenTotal].Type = Crate->GenType;
        Crate->Nodes[Crate->GenTotal].Start = Start;
        Crate->Nodes[Crate->GenTotal].End = End;
        
        Crate->GenTotal++;
        Crate->GenNodes[Crate->GenType]++;
        
        if (StopCount-- == 0)
            return false;
    }
    
    Crate->HacksGenerated = true;
    return true;
}

NamedScript void CrateHack()
{
    CrateInfo RPGMap *Crate = &Crates[Player.CrateID];
    
    if (!Crate->HacksGenerated)
    {
        Crate->Tries = 3;
        
        Crate->NodeMax[0] = 8;
        Crate->NodeMax[1] = 8;
        Crate->NodeMax[2] = 1;
        Crate->NodeMax[3] = 2;
        Crate->NodeMax[4] = 2;
        Crate->NodeMax[5] = 1;
        Crate->NodeMax[6] = 1;
        Crate->NodeMax[7] = 1;

        // DRLA - Technician gets bonuses
        if (CompatMode == COMPAT_DRLA && PlayerClass(PlayerNumber()) == 2)
        {
            Crate->NodeMax[NODE_CRITFAIL] /= 4;
            Crate->NodeMax[NODE_EXPLODE] /= 4;
            Crate->NodeMax[NODE_XP] *= 2;
            Crate->NodeMax[NODE_RANK] *= 2;
            Crate->NodeMax[NODE_RETRY] *= 2;
            Crate->NodeMax[NODE_ADD] *= 2;
        }
        
        // Initialize things
        for (int i = 0; i < MAX_NODES; i++)
            Crate->Nodes[i].Active = false;
        for (int i = 0; i < NODE_MAX; i++)
            Crate->GenNodes[i] = 0;
        
        while (!GenerateCrateNodes(Crate));
    };
    
    bool Hacking = true;
    int X = Random(25, 275);
    int Direction = (Random(1, 2) == 1 ? -1 : 1);
    
    // Prevent the use input from leaking into the input handling below (aka exploding a crate immediately in your face)
    Delay(4);
    
    ActivatorSound("hacking/begin", 127);
    
    SetPlayerProperty(0, 1, PROP_TOTALLYFROZEN);
    Crates[Player.CrateID].Hacking = PlayerNumber();
    Player.CrateHacking = true;
    
    while (Hacking)
    {
        int Buttons = GetPlayerInput(PlayerNumber(), INPUT_BUTTONS);
        int OldButtons = GetPlayerInput(PlayerNumber(), INPUT_OLDBUTTONS);
        
        SetHudSize(320, 240, false);
        
        // HACKIFICATIONS
        SetFont("SMALLFONT");
        HudMessage("HACKING IN PROGRESS...");
        EndHudMessage(HUDMSG_PLAIN, 0, "Green", 160.0, 100.0, 0.05);
        if (!GetActivatorCVar("drpg_toaster"))
            for (int i = 0; i < 16; i++)
            {
                HudMessage("%d", Random(0, 1));
                EndHudMessage(HUDMSG_FADEOUT, 0, "Green", 10.0 + (8.0 * Random(1, 36)), 150.0 + (8.0 * Random(1, 10)), 0.25, 0.75);
            }
        
        // Cursor
        PrintSprite("HackCurs", 0, 10.1 + X, 120.0, 0.05);
        
        // Nodes
        for (int i = 0; i < MAX_NODES; i++)
            if (Crate->Nodes[i].Active)
                DrawBar(StrParam("HackNod%d", Crate->Nodes[i].Type + 1), 10 + Crate->Nodes[i].Start, 120, Crate->Nodes[i].End, true);
        
        // Back
        DrawBar(StrParam("HackBor%d", Crate->Tries), 10, 120, 300, true);
        PrintSprite("HackBack", 0, 10.1, 120.0, 0.05);
        
        // Move Cursor
        X += Direction;
        if ((Crates[Player.CrateID].Rarity / 3) > 0)
            X += ((Crates[Player.CrateID].Rarity / 3) * Direction);
        if (X < 0)
        {
            X = 0;
            Direction = -Direction;
        }
        else if (X > 300)
        {
            X = 300;
            Direction = -Direction;
        }
        
        // Input
        if (Buttons == BT_USE && OldButtons != BT_USE)
        {
            bool HitNothing = true;
            long int XPBonus = XPTable[Player.Level] / 100l;
            long int RankBonus = RankTable[Player.RankLevel] / 100l;
            
            // Check Nodes
            for (int i = 0; i < MAX_NODES; i++)
                if (Crate->Nodes[i].Active)
                    if (X >= Crate->Nodes[i].Start && X <= Crate->Nodes[i].Start + Crate->Nodes[i].End)
                    {
                        HitNothing = false;
                        Crate->Nodes[i].Active = false;
                        
                        switch (Crate->Nodes[i].Type)
                        {
                        case NODE_CRITFAIL:
                            ActivatorSound("hacking/critfail", 127);
                            SetFont("SMALLFONT");
                            HudMessage("Security Lockdown Triggered!");
                            EndHudMessage(HUDMSG_FADEOUT, 0, "Red", 160.0, 140.0, 2.0, 1.0);
                            Crates[Player.CrateID].HackingCooldown += 35 * 60;
                            Crate->Tries = 3;
                            Hacking = false;
                            break;
                        case NODE_EXPLODE:
                            ActivatorSound("hacking/critfail", 127);
                            SetFont("SMALLFONT");
                            HudMessage("Explosive Device Triggered!");
                            EndHudMessage(HUDMSG_FADEOUT, 0, "Orange", 160.0, 140.0, 2.0, 1.0);
                            SetActorState(Crates[Player.CrateID].TID, "Explode");
                            Hacking = false;
                            Player.CrateOpen = false;
                            break;
                        case NODE_UNLOCK:
                            ActivatorSound("hacking/success", 127);
                            SetFont("SMALLFONT");
                            HudMessage("Hack Successful");
                            EndHudMessage(HUDMSG_FADEOUT, 0, "Green", 160.0, 140.0, 2.0, 1.0);
                            Crates[Player.CrateID].Firewall = false;
                            SetActorState(Crates[Player.CrateID].TID, "Normal");
                            SetUserVariable(Crates[Player.CrateID].TID, "user_firewall", (int)Crates[CrateID].Firewall);
                            Hacking = false;
                            break;
                        case NODE_XP:
                            ActivatorSound("hacking/select", 127);
                            SetFont("SMALLFONT");
                            HudMessage("+%ld XP", XPBonus);
                            EndHudMessage(HUDMSG_FADEOUT, 0, "White", 160.0, 140.0, 2.0, 1.0);
                            Player.XP += XPBonus;
                            break;
                        case NODE_RANK:
                            ActivatorSound("hacking/select", 127);
                            SetFont("SMALLFONT");
                            HudMessage("+%ld Rank", RankBonus);
                            EndHudMessage(HUDMSG_FADEOUT, 0, "Yellow", 160.0, 140.0, 2.0, 1.0);
                            Player.Rank += RankBonus;
                            break;
                        case NODE_RETRY:
                            ActivatorSound("hacking/select", 127);
                            SetFont("SMALLFONT");
                            HudMessage("Extra Try");
                            EndHudMessage(HUDMSG_FADEOUT, 0, "Blue", 160.0, 140.0, 2.0, 1.0);
                            if (Crate->Tries < 3)
                                Crate->Tries++;
                            break;
                        case NODE_ADD:
                            ActivatorSound("hacking/select", 127);
                            SetFont("SMALLFONT");
                            HudMessage("Extra Item!");
                            EndHudMessage(HUDMSG_FADEOUT, 0, "Cyan", 160.0, 140.0, 2.0, 1.0);
                            if (Crates[Player.CrateID].Amount < CRATE_MAX_ITEMS - 1)
                                Crates[Player.CrateID].Amount++;
                            break;
                        case NODE_RARITY:
                            ActivatorSound("hacking/select", 127);
                            SetFont("SMALLFONT");
                            HudMessage("Rarity Upgrade!");
                            EndHudMessage(HUDMSG_FADEOUT, 0, "Purple", 160.0, 140.0, 2.0, 1.0);
                            if (Crates[Player.CrateID].Rarity < MAX_DIFFICULTIES - 1)
                                Crates[Player.CrateID].Rarity++;
                            break;
                        }
                        
                        break;
                    }
            
            if (HitNothing)
            {
                ActivatorSound("hacking/select", 127);
                Crate->Tries--;
                
                // You fail it
                if (Crate->Tries <= 0)
                {
                    ActivatorSound("hacking/fail", 127);
                    Crates[Player.CrateID].HackingCooldown += 35 * 30;
                    Crate->Tries = 3;
                    Hacking = false;
                }
            }
        }
        if (Buttons & BT_SPEED)
        {
            ActivatorSound("hacking/select", 127);
            Hacking = false;
        }
        
        Delay(1);
    }
    
    Delay(4);
    
    SetPlayerProperty(0, 0, PROP_TOTALLYFROZEN);
    Crates[Player.CrateID].Hacking = -1;
    Player.CrateHacking = false;
}

typedef struct _setinfo
{
    str Name;
    str Token;
    bool Synthfire;
    
    struct SetItemInfo
    {
        str Name;
        fixed Chance;
    } Items[32];
} SetInfo;
        
void GenerateCrate(int ID, int Amount)
{
    int i;
    int Firewalls;
    
    if (Crates[ID].SupplyDrop)
    {
        ItemInfoPtr Backpack = FindItem("DRPGBigBackpack");
        
        if (Backpack == GetBlankItem())
        {
            Log("\CgWARNING: Couldn't find the backpack item!");
        }
        
        int NumPlayers = PlayerCount();
        
        // Create a backpack for every player in the game
        for (int j = 0; j < NumPlayers; j++)
        {
            Crates[ID].Active[i] = true;
            Crates[ID].Item[i] = Backpack;
            i++;
        }
    }
    
    for (; i < Amount; i++)
    {
        ItemInfoPtr item = GetRewardItem(Crates[ID].Rarity);
        
        if (item == GetBlankItem())
        {
            i--;
            continue;
        }
        
        Crates[ID].Active[i] = true;
        Crates[ID].Item[i] = item;
    }
    
    // DRLA Set shenanigans
    if (CompatMode == COMPAT_DRLA)
    {
        SetInfo const SetItems[MAX_DRLA_SETS] =
        {
            {
                "Death From Above", "RLDeathFromAboveSetBonusActive", false,
                {
                    { "RLAntigravSteelBoots",               40, },
                    { "RLAntigravProtectiveBoots",          30, },
                    { "RLAntigravPlasteelBoots",            20, },
                    { "RLJetpackArmor",                     40, },    
                    { NULL, },
                },
            },
            {
                "Demonic", "RLDemonicSetBonusActive", false,
                {
                    { "RLDemonicCarapaceArmor",             40, },
                    { "RLDemonicBoots",                     40, },
                    { NULL, },
                },
            },
            {
                "Tactical", "RLTacticalSetBonusActive", false,
                {
                    { "RLTacticalArmor",                    40, },
                    { "RLTacticalBoots",                    40, },
                    { NULL, },
                },
            },
            {
                "Gothic", "RLGothicSetBonusActive", false,
                {
                    { "RLGothicArmor",                      40, },
                    { "RLGothicBoots",                      40, },
                    { NULL, },
                },
            },
            {
                "Phaseshift", "RLPhaseshiftSetBonusActive", false,
                {
                    { "RLPhaseshiftArmor",                  40, },
                    { "RLPhaseshiftBoots",                  40, },
                    { NULL, },
                },
            },
            {
                "Roysten", "RLRoystenSetBonusActive", false,
                {
                    { "RLRoystensCommandArmor",             25, },
                    { "RLRoystensCombatBoots",              25, },
                    { NULL, },
                },
            },
            {
                "Architect", "RLArchitectSetBonusActive", false,
                {
                    { "RLSoloOperativeSuitArmor",           25, },
                    { "RLSoloOperativeBoots",               25, },
                    { NULL, },
                },
            },
            {
                "Torgue", "RLTorgueSetBonusActive", false,
                {
                    { "RLTorgueBlastplateArmor",            25, },
                    { "RLTorgueBlastBoots",                 25, },
                    { NULL, },
                },
            },
            {
                "Enclave", "RLEnclaveSetBonusActive", false,
                {
                    { "RLNuclearPowerArmor",                25, },
                    { "RLNuclearPowerBoots",                25, },
                    { NULL, },
                },
            },
            {
                "Sentry Sentinel", "RLSentrySentinelSetBonusActive", false,
                {
                    { "RLTacticalAssemblerSuitArmor",       25, },
                    { "RLTacticalAssemblerBoots",           25, },
                    { NULL, },
                },
            },
            {
                "Sensible Strategist", "RLSensibleStrategistSetBonusActive", false,
                {
                    { "RLTacticalAssemblerSuitArmor",       25, },
                    { "RLTacticalAssemblerBoots",           25, },
                    { NULL, },
                },
            },
            {
                "Lava", "RLLavaSetBonusActive", false,
                {
                    { "RLLavaArmor",                        20, },
                    { "RLLavaBoots",                        20, },
                    { NULL, },
                },
            },
            {
                "Inquisitor", "RLInquisitorsSetBonusActive", false,
                {
                    { "RLMaleksArmor",                      20, },
                    { "RLNyarlaptotepsBoots",               20, },
                    { NULL, },
                },
            },
            {
                "Cerberus", "RLCerberusSetBonusActive", false,
                {
                    { "RLTristarBlaster",                   25, },
                    { "RLCerberusArmor",                    25, },
                    { "RLCerberusBoots",                    25, },
                    { NULL, },
                },
            },
            {
                "Angelic", "RLAngelicAttireSetBonusActive", false,
                {
                    { "RLAngelicArmor",                     10, },
                    { "RLAngelicBoots",                     10, },
                    { NULL, },
                },
            },
            {
                "Nuclear", "RLNuclearWeaponSetBonusActive", false,
                {
                    { "RLNuclearPlasmaPistol",              25, },
                    { "RLNuclearPlasmaRifle",               15, },
                    { "RLNuclearBFG9000",                   10, },
                    { "RLNuclearOnslaught",                 0.2, },
                    { "RLNuclearArmor",                     20, },
                    { "RLNuclearPowerArmor",                3, },
                    { "RLHighPowerNuclearPlasmaPistol",     0, },
                    { "RLStormNuclearPlasmaPistol",         0, },
                    { "RLSuperchargedNuclearPlasmaPistol",  0, },
                    { "RLNuclearPlasmaShotgun",             0, },
                    { "RLNuclearPlasmaRifleMkII",           0, },
                    { "RLAssaultRifleNuclearPlasmaRifle",   0, },
                    { "RLBurstCannonNuclearPlasmaRifle",    0, },
                    { "RLHighPowerNuclearPlasmaRifle",      0, },
                    { "RLHighPowerNuclearBFG9000",          0, },
                    { "RLNuclearVBFG9000",                  0, },
                    { "RLNuclearBiggestFuckingGun",         0, },
                    { "RLNuclearPlasmaRevolver",            0, },
                    { "RLNuclearOnslaught",                 0, },
                    { NULL, },
                },
            },
            {
                "Alucard", "RLAntiFreakJackalDemonArtifacts", false,
                {
                    { "RLAntiFreakJackal",                  10, },
                    { "RLHellsingARMSCasull",               10, },
                    { NULL, },
                },
            },
            {
                "Security Officer", "RLMarathonShotgunsDemonArtifacts", true,
                {
                    { "RLMarathonShotguns",                 10, },
                    { NULL, },
                },
            },
        };
        
        int SetAmount = Amount;
        
        if (GetCVar("drpg_debug"))
            Log("\CdDEBUG: \C-Checking DRLA sets...");
        
        for (int i = 0; i < MAX_DRLA_SETS; i++)
        {
            if (GetCVar("drpg_debug"))
                Log("\CdDEBUG: \C-Set \Cd%d\C-: \Cd%S", i + 1, SetItems[i].Name);
            
            // Skip this set if you already have it
            if (CheckInventory(SetItems[i].Token)) continue;
            
            bool HaveItem = false;
            for (int j = 0; SetItems[i].Items[j].Name != NULL; j++)
            {
                if (GetCVar("drpg_debug"))
                    Log("\CdDEBUG: \C-Set \Cd%d \C-Item \Cd%d\C-: \Cd%S", i + 1, j + 1, SetItems[i].Items[j].Name);
                
                if (CheckInventory(SetItems[i].Items[j].Name) || CheckInventory(StrParam("%SToken", SetItems[i].Items[j].Name)))
                {
                    HaveItem = true;
                    if (GetCVar("drpg_debug"))
                        Log("\CdDEBUG: \C-Have this item, continue...");
                    break;
                }
            }
            
            if (HaveItem)
            {
                for (int j = 0; SetItems[i].Items[j].Name != NULL; j++)
                {
                    str PickupItemName = StrParam("%SPickup", SetItems[i].Items[j].Name);
                    ItemInfoPtr ItemPtr = FindItem(PickupItemName);
                    fixed Chance = SetItems[i].Items[j].Chance * (1.0 + (Crates[ID].Rarity * 0.125));
                    fixed Pick = RandomFixed(0.0, 100.0);
                    
                    // Skip this item if you have it and it's not a dual/synthfire set
                    if (!SetItems[i].Synthfire && CheckInventory(SetItems[i].Items[j].Name) || CheckInventory(StrParam("%SToken", SetItems[i].Items[j].Name))) continue;
                    
                    // Stop checking items if we've filled the crate
                    if (SetAmount >= CRATE_MAX_ITEMS)
                    {
                        if (GetCVar("drpg_debug"))
                            Log("\CdDEBUG: \C-Crate is full! Stopping set checks");
                        return;
                    }
                    
                    if (GetCVar("drpg_debug"))
                        Log("\CdDEBUG: \C-Set \Cd%d \C-Item \Cd%d\C-: \Cd%S \C-(Chance: \Cf%.2k%% \C-/ Pick: \Cf%.2k%%\C-)", i + 1, j + 1, SetItems[i].Items[j].Name, Chance, Pick);
                    
                    if (Pick <= Chance)
                    {
                        // Couldn't find the item
                        if (ItemPtr == GetBlankItem()) continue;
                        
                        Crates[ID].Active[SetAmount] = true;
                        Crates[ID].Item[SetAmount] = ItemPtr;
                        
                        if (GetCVar("drpg_debug"))
                            Log("\CdDEBUG: \CfSet Item Spawned!");
                        
                        SetAmount++;
                    }
                }
            }
        }
    }
}

void CrateTakeItem()
{
    bool Spawned = SpawnForced(Crates[Player.CrateID].Item[Player.CrateIndex]->Actor, GetActorX(0), GetActorY(0), GetActorZ(0), 0, 0);
    
    if (Spawned)
    {
        SetActorVelocity(Player.TID, 0.01, 0.01, 0, true, false);
        
        Crates[Player.CrateID].Active[Player.CrateIndex] = false;
        Crates[Player.CrateID].Item[Player.CrateIndex] = NULL;
    }
}

bool CrateEmpty(int ID)
{
    for (int i = 0; i < CRATE_MAX_ITEMS; i++)
        if (Crates[ID].Active[i])
            return false;
    
    return true;
}

// TODO: Tried to make this a more generic ItemSpace CrateInfo *FindCrate, but DH-ACC bitched, yell at David
// TODO: Actually fix this for GDCC
bool CrateEmptyTID(int TID)
{
    for (int i = 0; i < CrateID; i++)
        if (Crates[i].TID == TID)
            return Crates[i].Empty;
    
    return false;
}

void DrawCrate()
{
    // Width/Height
    int Width = 9;
    int Height = 6;
    
    // Coordinates
    fixed BaseX;
    fixed BaseY;
    fixed BoxX;
    fixed BoxY;
    fixed X;
    fixed Y;
    fixed IconX;
    fixed IconY;
    
    // Title
    SetFont("BIGFONT");
    HudMessage("UAC Supply Crate (%S\C-)", CrateRarityNames[Crates[Player.CrateID].Rarity]);
    EndHudMessage(HUDMSG_PLAIN, 0, "Green", 24.1, 24.0, 0.05);
    
    for (int i = 0; i < Height; i++)
    {
        // Reset base X
        BaseX = 0.0;
        
        for (int j = 0; j < Width; j++)
        {
            int Index = j + (i * Width);
            
            ItemInfoPtr Item = Crates[Player.CrateID].Item[Index];
            bool Active = Crates[Player.CrateID].Active[Index];
            str Icon = Item->Sprite.Name;
            str Name = Item->Name;
            int IconXOff = Item->Sprite.XOff;
            int IconYOff = Item->Sprite.YOff;
            
            // Setup X and Y
            X = 26.0 + BaseX;
            Y = 50.0 + BaseY;
            BoxX = 48.0 + BaseX;
            BoxY = 72.0 + BaseY;
            IconX = 48.0 + BaseX;
            IconY = 72.0 + BaseY;
            IconX += IconXOff;
            IconY += IconYOff;
            
            // Icon
            SetHudClipRect(X, Y, 44, 44);
            if (Active)
                if (Player.CrateIndex == Index)
                    PrintSpritePulse(Icon, 0, IconX, IconY, 0.75, 32.0, 0.25);
                else
                    PrintSprite(Icon, 0, IconX, IconY, 0.05);
            SetHudClipRect(0, 0, 0, 0);
            
            // Box
            if (Player.CrateIndex == Index)
            {
                if (Active)
                    PrintSprite("ItemBoxH", 0, BoxX, BoxY, 0.05);
                else
                    PrintSprite("ItemBoxR", 0, BoxX, BoxY, 0.05);
            }
            PrintSprite("ItemBoxB", 0, BoxX, BoxY, 0.05);
            
            // Item Name
            if (Player.CrateIndex == Index && Active)
            {
                SetFont("BIGFONT");
                HudMessage("%S", Name);
                EndHudMessage(HUDMSG_PLAIN, 0, "White", 24.1, 344.1, 0.05);
            }
            
            // Increment X
            BaseX += 48.0;
        }
        
        // Increment Y
        BaseY += 48.0;
    }
}

void CrateInput()
{
    int Buttons = GetPlayerInput(PlayerNumber(), INPUT_BUTTONS);
    int OldButtons = GetPlayerInput(PlayerNumber(), INPUT_OLDBUTTONS);
    
    if (Buttons & BT_SPEED && !(OldButtons & BT_SPEED))
    {
        ActivatorSound("crate/close", 127);
        Player.CrateOpen = false;
        
        // Set the crate to it's inactive state if it's empty
        if (CrateEmpty(Player.CrateID))
        {
            SetActorState(Crates[Player.CrateID].TID, "Empty");
            Crates[Player.CrateID].Empty = true;
        }
    }
    if (Buttons & BT_USE && !(OldButtons & BT_USE))
    {
        ActivatorSound("menu/move", 127);
        CrateTakeItem();
    }
    if (Buttons & BT_FORWARD && !(OldButtons & BT_FORWARD))
    {
        ActivatorSound("menu/move", 127);
        Player.CrateIndex -= 9;
        if (Player.CrateIndex < 0) Player.CrateIndex = 0;
    }
    if (Buttons & BT_BACK && !(OldButtons & BT_BACK))
    {
        ActivatorSound("menu/move", 127);
        Player.CrateIndex += 9;
        if (Player.CrateIndex > CRATE_MAX_ITEMS - 1) Player.CrateIndex = CRATE_MAX_ITEMS - 1;
    }
    if ((Buttons & BT_LEFT && !(OldButtons & BT_LEFT)) ||
        (Buttons & BT_MOVELEFT && !(OldButtons & BT_MOVELEFT)))
    {
        ActivatorSound("menu/move", 127);
        Player.CrateIndex--;
        if (Player.CrateIndex < 0) Player.CrateIndex = 0;
    }
    if ((Buttons & BT_RIGHT && !(OldButtons & BT_RIGHT)) ||
        (Buttons & BT_MOVERIGHT && !(OldButtons & BT_MOVERIGHT)))
    {
        ActivatorSound("menu/move", 127);
        Player.CrateIndex++;
        if (Player.CrateIndex > CRATE_MAX_ITEMS - 1) Player.CrateIndex = CRATE_MAX_ITEMS - 1;
    }
}

NamedScript Console void DumpCrate()
{
    for (int i = 0; i < CrateID; i++)
    {
        Log("\Cd  ===== Crate %d =====", i);
        Log("Amount: %d", Crates[i].Amount);
        Log("Rarity: %d", Crates[i].Rarity);
        
        for (int j = 0; j < CRATE_MAX_ITEMS; j++)
        {
            if (!Crates[i].Active[j]) continue;
            
            Log("%d. %S (%S)", j, Crates[i].Item[j]->Name, Crates[i].Item[j]->Actor);
        }
    }
}

ЕЯПП, то основной скрипт в коде - "NamedScript DECORATE void UseCrate(int ID)". На "Firewall" стэйт\актор и соответствующие скрипты не обращай внимания - это своеобразный "замок" ящиков.

Рейтинг сообщения: +1, отметил(и): Anto96WS
1 9 1
camper
- Master Sergeant -
Next rank: = Master Sergeant = after 28 points
432

Doom Rate: 1.43

Posts quality: +253
Ссылка на пост №3176 Отправлено: 27.04.18 00:06:51
+Ku6EPyXOBEPTKA+:
Зато в многро этажных и сложных конструкциях можно отыграться, так как позволяет не просто делать объёмные фигуры любой формы, но и не сковывает в пространстве.

Спасибо.
Нашел на zdoom форуме туториал еще Ссылка

Рейтинг сообщения: +1, отметил(и): Doomstalker
Void Weaver
= Captain =
Next rank: - Major - after 144 points
2496

Doom Rate: 1.82

Posts quality: +807
Ссылка на пост №3177 Отправлено: 28.04.18 00:56:52
Господа, подсобите с парой вопросов:

1) прописан A_CheckLOF со следующими параметрами:
Скрытый текст:

("Melee",CLOFF_JUMPENEMY|CLOFF_JUMPFRIEND|CLOFF_JUMPOBJECT|CLOFF_JUMPNONHOSTILE|CLOFF_JUMP_ON_MISS|CLOFF_CHECKPARTIAL|CLOFF_SETTARGET,128,0,360,13,0,0,AAPTR_DEFAULT,0)

всё ок кроме того что без флага "CLOFF_JUMPNONHOSTILE" актор не атакует препятствия. Но когда флаг выставлен, актор вдобавок "атакует" трупы ранее убитых им врагов. Т. е. бежит себе актор, чекает ЛОФ, и если натыкается на труп, то останавливается и пытается его атаковать.
Как это пофиксить?


2) актор спаунит через A_SpawnItemEx ("Cripple",0,0,0,0,0,0,0,SXF_NOCHECKPOSITION|SXF_TRANSFERPOINTERS) такой снаряд:
Скрытый текст:

Actor Cripple
{
        Speed 60
	Radius 2
	//Damage 0
	Projectile
	States
        {
        Spawn:
	TNT1 AAAAAAAAAA 35 A_DamageTarget(random(1,3),None,DMSS_FOILINVUL|DMSS_AFFECTARMOR|DMSS_NOPROTECT,AAPTR_TARGET)
	Stop
        Death:
	TNT1 A 0
	Stop
        }
}

Цель начинает получать урон, но не атакует владельца снаряда. В чём дело и как исправить? Может прописать в снаряде флаг какой-нибудь чтобы цель сразу агрилась?

3) кто-нибудь может объяснить параметры A_TransferPointer? А то чего-то на инглише не догоняю кто кому чей поинтер передаёт и получает. Я правильно понимаю что эта функция является расширенной версией A_CopyFriendliness?
1 9 1
MyNameIs
= 1st Lieutenant =
Next rank: - Captain - after 60 points
2030

Doom Rate: 2.05

Posts quality: +876
Ссылка на пост №3178 Отправлено: 28.04.18 10:45:02
а есть способ скриптом проверить наличие определенного (или хотя бы любого) актора в указанной точке?


Void Weaver:
и если натыкается на труп, то останавливается и пытается его атаковать.

можно попробовать прописать трупкау в стейте смерти какой-нибудь A_NoBlocking, или A_UnsetSolid
1 1 1
JSO x
- 2nd Lieutenant -
Next rank: = 2nd Lieutenant = after 142 points
1298

Doom Rate: 2.29

Posts quality: +698
Ссылка на пост №3179 Отправлено: 28.04.18 11:57:21
2 Void Weaver:

1) Попробуй дописать флаг "CLOFF_MUSTBESOLID" (цель должна быть непроходимой). Тогда трупы он бить точно не будет.

2) C A_DamageTarget:

src: Indicates the actor pointer responsible for dealing the damage. <...> Missiles should use AAPTR_TARGET (so monsters can identify missiles belonging to their owners and infight with them). Default is AAPTR_DEFAULT.


3) A_TransferPointer( <от кого брать указатель>, <кому передать указатель>, <какой указатель взять>, <какой указатель заменить> [, <доп. флаги> ] ). То есть актор со строкой
A_TransferPointer( AAPTR_TARGET, AAPTR_DEFAULT, AAPTR_MASTER, AAPTR_MASTER )

будет считать мастера своей цели и своим мастером тоже, как дойдёт до этой строки.

И нет, A_TransferPointer и A_CopyFriendliness не особо похожи. Последняя функция меняет отношение вызывающего её к другим также, как относится к ним указатель (параметр).




MyNameIs, можно через функцию Spawn с классом, который выполняет CheckActorClass ( "A_JumpIf( CheckActorClass( <class> ), <state> )" ).

Рейтинг сообщения: +2, отметил(и): alekv, Void Weaver
2 7 1
Anto96WS
= Master Corporal =
Next rank: - Sergeant - after 9 points
281

Doom Rate: 1.77

Posts quality: +88
Ссылка на пост №3180 Отправлено: 28.04.18 17:12:34
Можно ли в GZDB опускать\поднимать полы группами? (Полы разных высот)
Страница 159 из 200Перейти наверх Пред.  1, 2, 3 ... 158, 159, 160 ... 198, 199, 200  След.
   Список разделов - Флуд и устаревшие темы - Тема для новичков. Вопросы по маппингу/моддингу - любые!